summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael H. Schloming <rhs@apache.org>2008-08-15 03:40:49 +0000
committerRafael H. Schloming <rhs@apache.org>2008-08-15 03:40:49 +0000
commitb6a376a4797e4988cdae48e0e5395a9b1f4e9f85 (patch)
treedc41b190202b592d35579af35cc8b18bb1f1b702
parentc521097d6d6f44e437e2ce67f5a8ae66706e4476 (diff)
downloadqpid-python-b6a376a4797e4988cdae48e0e5395a9b1f4e9f85.tar.gz
updated qpid.0-10/java to match trunk/qpid/java@686097
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/qpid.0-10@686136 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/010ExcludeList18
-rw-r--r--java/010ExcludeList-noPrefetch55
-rw-r--r--java/010ExcludeList-store15
-rw-r--r--java/08ExcludeList3
-rw-r--r--java/08ExcludeList-nonvm24
-rw-r--r--java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java19
-rw-r--r--java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java25
-rw-r--r--java/broker/bin/qpid-passwd5
-rw-r--r--java/broker/bin/qpid-server8
-rw-r--r--java/broker/bin/qpid-server.bat161
-rw-r--r--java/broker/etc/acl.config.xml2
-rw-r--r--java/broker/src/main/grammar/SelectorParser.jj2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java575
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Main.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java55
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java104
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java66
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java (renamed from java/client/src/main/java/org/apache/qpid/client/state/StateListener.java)20
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java579
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java (renamed from java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java)69
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java26
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java41
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java650
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKey.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKeyDictionary.java50
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderMatcherResult.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersMatcherDFAState.java339
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java439
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java295
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java613
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java63
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java141
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java14
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java126
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/NoConsumerFilter.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java332
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java322
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java62
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java77
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java44
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java44
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java79
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java76
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java185
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java105
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java288
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java129
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java240
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java25
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java1132
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java328
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java172
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java66
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java114
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java122
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java569
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java767
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java133
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java92
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java92
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java472
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java71
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java1006
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java52
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java1097
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/DeliveryManager.java102
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java84
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java57
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java71
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java307
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java267
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java169
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java243
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java388
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java26
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java1638
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java178
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java680
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionManager.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java274
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java66
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/WeightedSubscriptionManager.java26
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java110
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java49
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java35
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java28
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java (renamed from java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java)65
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java (renamed from java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java)24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java103
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java605
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java247
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java77
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java148
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java70
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java23
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/NullApplicationRegistry.java51
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java88
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java52
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java140
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Select.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java2
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java120
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java176
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java11
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java173
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/protocol/TestMinaProtocolSession.java52
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java116
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java94
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java178
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java66
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java86
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/amqplain/AMQPlainSaslServerTest.java43
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerTest.java (renamed from java/systests/src/main/java/org/apache/qpid/test/VMBrokerSetup.java)41
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreShutdownTest.java81
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java632
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java182
-rw-r--r--java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java (renamed from java/systests/src/main/java/org/apache/qpid/server/util/TestApplicationRegistry.java)78
-rw-r--r--java/build.deps5
-rw-r--r--java/build.xml27
-rw-r--r--java/client/build.xml3
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java6
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java31
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java16
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java6
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java26
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java20
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java18
-rwxr-xr-xjava/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java26
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify7
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_cpp_java2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_cpp2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_python4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_python_java4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_cpp_java2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_cpp2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_python4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_python_java4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_cpp_java2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_cpp2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_python4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_python_java4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_cpp_java5
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_cpp2
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_python4
-rw-r--r--java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_python_java4
-rw-r--r--java/client/pom.xml8
-rw-r--r--java/client/src/main/grammar/SelectorParser.jj20
-rw-r--r--java/client/src/main/java/client.log4j5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnection.java243
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java3
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java22
-rwxr-xr-xjava/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_9.java32
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java (renamed from java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_8.java)47
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java36
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQDestination.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java552
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java149
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java139
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java104
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java146
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java42
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java40
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java139
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java13
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java12
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java37
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java8
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java12
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java9
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java9
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java14
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java11
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java91
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java39
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionOpenOkMethodHandler.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionSecureMethodHandler.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java9
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java7
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessage.java135
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java138
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java54
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java973
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java567
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java26
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java20
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java569
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java73
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/CloseConsumerMessage.java43
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java25
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java11
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java16
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java23
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java11
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java56
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java11
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java27
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java11
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java67
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java12
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java41
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java9
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java32
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage.java71
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_10.java61
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java41
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java125
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java164
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java107
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java145
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java185
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/StateAwareMethodListener.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java149
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java4
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java180
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java348
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java23
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/ArithmeticExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/BinaryExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/BinaryExpression.java)2
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/BooleanExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/BooleanExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/ComparisonExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/ConstantExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/ConstantExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/Expression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/Expression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java)6
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/LogicExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/LogicExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/MessageFilter.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/MessageFilter.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/PropertyExpression.java)78
-rw-r--r--java/client/src/main/java/org/apache/qpid/filter/UnaryExpression.java (renamed from java/client/src/main/java/org/apache/qpidity/filter/UnaryExpression.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/Message.java2
-rw-r--r--java/client/src/main/java/org/apache/qpid/naming/ReadOnlyContext.java (renamed from java/client/src/main/java/org/apache/qpidity/naming/ReadOnlyContext.java)2
-rw-r--r--java/client/src/main/java/org/apache/qpid/naming/jndi.properties (renamed from java/client/src/main/java/org/apache/qpidity/naming/jndi.properties)2
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/Client.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/Client.java)97
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/ClosedListener.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/ClosedListener.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/Connection.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/Connection.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/DtxSession.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java)26
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/JMSTestCase.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/JMSTestCase.java)2
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/MessagePartListener.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/MessagePartListener.java)31
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/Session.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/Session.java)151
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSession.java142
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSessionDelegate.java47
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/impl/Constants.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/impl/Constants.java)2
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/impl/DemoClient.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java)53
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/interop/BasicInteropTest.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java)47
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/util/ByteBufferMessage.java)59
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/FileMessage.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/util/FileMessage.java)10
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/MessageListener.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/util/MessageListener.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java67
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/ReadOnlyMessage.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/util/ReadOnlyMessage.java)8
-rw-r--r--java/client/src/main/java/org/apache/qpid/nclient/util/StreamingMessage.java (renamed from java/client/src/main/java/org/apache/qpidity/nclient/util/StreamingMessage.java)10
-rw-r--r--java/client/src/main/java/org/apache/qpid/njms/ExceptionHelper.java (renamed from java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.java)4
-rw-r--r--java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java204
-rw-r--r--java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java79
-rw-r--r--java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java76
-rw-r--r--java/client/src/main/java/org/apache/qpidity/nclient/util/MessagePartListenerAdapter.java59
-rw-r--r--java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java125
-rw-r--r--java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java8
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java6
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java35
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java1
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java32
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java171
-rw-r--r--java/client/src/test/java/org/apache/qpid/testutil/Config.java199
-rw-r--r--java/common.xml23
-rw-r--r--java/common/Composite.tpl73
-rw-r--r--java/common/Constant.tpl2
-rw-r--r--java/common/Enum.tpl2
-rw-r--r--java/common/Invoker.tpl13
-rw-r--r--java/common/MethodDelegate.tpl2
-rw-r--r--java/common/Option.tpl5
-rw-r--r--java/common/StructFactory.tpl2
-rw-r--r--java/common/Type.tpl2
-rwxr-xr-xjava/common/bin/qpid-run48
-rwxr-xr-xjava/common/codegen2
-rw-r--r--java/common/genutil.py17
-rw-r--r--java/common/pom.xml2
-rw-r--r--java/common/src/main/java/log4j.properties3
-rw-r--r--java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java63
-rw-r--r--java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java1
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQChannelException.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java18
-rw-r--r--java/common/src/main/java/org/apache/qpid/BrokerDetails.java (renamed from java/common/src/main/java/org/apache/qpidity/BrokerDetails.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java (renamed from java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/ConsoleOutput.java (renamed from java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java)11
-rw-r--r--java/common/src/main/java/org/apache/qpid/ErrorCode.java (renamed from java/common/src/main/java/org/apache/qpidity/ErrorCode.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/QpidConfig.java (renamed from java/common/src/main/java/org/apache/qpidity/QpidConfig.java)8
-rw-r--r--java/common/src/main/java/org/apache/qpid/QpidException.java (renamed from java/common/src/main/java/org/apache/qpidity/QpidException.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/SecurityHelper.java (renamed from java/common/src/main/java/org/apache/qpidity/SecurityHelper.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyBroker.java (renamed from java/common/src/main/java/org/apache/qpidity/ToyBroker.java)143
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyClient.java (renamed from java/common/src/main/java/org/apache/qpidity/ToyClient.java)40
-rw-r--r--java/common/src/main/java/org/apache/qpid/ToyExchange.java (renamed from java/common/src/main/java/org/apache/qpidity/ToyExchange.java)39
-rw-r--r--java/common/src/main/java/org/apache/qpid/api/Message.java (renamed from java/common/src/main/java/org/apache/qpidity/api/Message.java)8
-rw-r--r--java/common/src/main/java/org/apache/qpid/common/ClientProperties.java23
-rw-r--r--java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java (renamed from java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java)8
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java67
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java20
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTable.java105
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/Job.java24
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java30
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java432
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java27
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java24
-rw-r--r--java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java7
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java (renamed from java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java (renamed from java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java)4
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java (renamed from java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java)4
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/JCAProvider.java (renamed from java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java (renamed from java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java (renamed from java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java (renamed from java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Binary.java129
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Binding.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Binding.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Channel.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Channel.java)76
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java)7
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Connection.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Connection.java)34
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java)46
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java45
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Echo.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Echo.java)31
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Field.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Field.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Future.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Future.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Header.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Header.java)51
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Method.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Method.java)97
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java)19
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java)23
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java)30
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Range.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Range.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/RangeSet.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java)7
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Receiver.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Receiver.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Result.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Result.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Sender.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Sender.java)4
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Session.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Session.java)156
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java39
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java)8
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/SessionException.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/SessionException.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Sink.java137
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/Struct.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/Struct.java)8
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/TransportException.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/TransportException.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java)78
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java)171
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java)23
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java232
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java226
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java)55
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java236
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/Frame.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java)52
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java204
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java)6
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java109
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java81
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java129
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java291
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java174
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java)61
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java)11
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java)18
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java)9
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/util/Functions.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/util/Logger.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java)7
-rw-r--r--java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java (renamed from java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java)2
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/QpidURL.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java4
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java59
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java39
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/Strings.java82
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/UUIDGen.java36
-rw-r--r--java/common/src/main/java/org/apache/qpid/util/UUIDs.java (renamed from java/client/src/test/java/org/apache/qpid/testutil/VMBrokerSetup.java)45
-rw-r--r--java/common/src/main/java/org/apache/qpidity/ProtocolException.java36
-rw-r--r--java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java51
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/Data.java108
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java29
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java112
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java134
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java76
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java177
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java202
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java222
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java277
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java116
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java181
-rw-r--r--java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java111
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java (renamed from java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java)16
-rw-r--r--java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java (renamed from java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java)2
-rw-r--r--java/cpp.async.testprofile15
-rw-r--r--java/cpp.noprefetch.testprofile4
-rw-r--r--java/cpp.sync.testprofile18
-rw-r--r--java/cpp.testprofile15
-rw-r--r--java/default-longrunning.testprofile1
-rw-r--r--java/default.testprofile16
-rwxr-xr-xjava/integrationtests/bin/interoptests.py180
-rw-r--r--java/java.testprofile5
-rw-r--r--java/junit-toolkit/pom.xml25
-rw-r--r--java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java5
-rw-r--r--java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java134
-rw-r--r--java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java2
-rw-r--r--java/log4j-test.xml14
-rw-r--r--java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java10
-rw-r--r--java/module.xml19
-rw-r--r--java/perftests/RunningPerformanceTests.txt2
-rw-r--r--java/perftests/build.xml290
-rwxr-xr-xjava/perftests/etc/scripts/Connections.sh21
-rwxr-xr-xjava/perftests/etc/scripts/MessageSize.sh20
-rwxr-xr-xjava/perftests/etc/scripts/Reliability.sh2
-rwxr-xr-xjava/perftests/etc/scripts/RunAll.sh25
-rwxr-xr-xjava/perftests/etc/scripts/Throughput.sh2
-rw-r--r--java/perftests/pom.xml11
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java7
-rw-r--r--java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java8
-rw-r--r--java/systests/pom.xml1
-rw-r--r--java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java125
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java (renamed from java/client/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java (renamed from java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java (renamed from java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java (renamed from java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java)28
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java (renamed from java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java)17
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java (renamed from java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java)9
-rw-r--r--java/systests/src/main/java/org/apache/qpid/client/message/NonQpidObjectMessage.java (renamed from java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java)8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java76
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java268
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java7
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java139
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java10
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java135
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/ConcurrencyTestDisabled.java265
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/DeliveryManagerTest.java177
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java21
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java23
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java176
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java17
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionManagerTest.java102
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionSetTest.java144
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java69
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java29
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java18
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/TestMemoryMessageStore.java (renamed from java/systests/src/main/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java)4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java48
-rw-r--r--java/systests/src/main/java/org/apache/qpid/server/txn/TxnBufferTest.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/VMTestCase.java165
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java37
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/FlowControlTest.java211
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java98
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java174
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/client/message/MessageToStringTest.java251
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java19
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java)8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java)8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/MapMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java)11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java)123
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java)5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/ReceiveTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java)18
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/SessionStartTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java)10
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/TextMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSessionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java)8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java)34
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java)4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java)76
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Client.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java)3
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Service.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Service.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java)8
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java)5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java)3
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java)4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java)5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java)7
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java)5
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java)11
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java)60
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java)82
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactedTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java)4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/xa/FaultTest.java)0
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/xa/QueueTest.java)4
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/xa/TopicTest.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/ConversationFactory.java (renamed from java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java)3
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java (renamed from java/systests/src/main/java/org/apache/qpid/test/FailoverBaseCase.java)33
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnection.java (renamed from java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java)6
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java (renamed from java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java)3
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java (renamed from java/client/src/main/java/org/apache/qpid/testutil/QpidTestCase.java)113
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtils.java (renamed from java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtilsException.java (renamed from java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java)2
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java (renamed from java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/TestIoSession.java)2
-rw-r--r--java/testkit/README153
-rw-r--r--java/testkit/bin/perf_report.sh100
-rw-r--r--java/testkit/bin/run_pub.sh24
-rw-r--r--java/testkit/bin/run_soak_client.sh70
-rw-r--r--java/testkit/bin/run_sub.sh25
-rw-r--r--java/testkit/bin/setenv.sh49
-rw-r--r--java/testkit/bin/soak_report.sh161
-rw-r--r--java/testkit/build.xml27
-rw-r--r--java/testkit/etc/jndi.properties35
-rw-r--r--java/testkit/etc/test.log4j28
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/MessageFactory.java43
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfBase.java102
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfConsumer.java248
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfProducer.java207
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/perf/TestParams.java160
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/BaseTest.java152
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedConsumer.java153
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedProducer.java166
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java138
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleConsumer.java134
-rw-r--r--java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleProducer.java146
-rw-r--r--java/tools/bin/qpid-bench35
-rw-r--r--java/tools/build.xml27
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/JNDICheck.java200
-rw-r--r--java/tools/src/main/java/org/apache/qpid/tools/QpidBench.java885
628 files changed, 29079 insertions, 16867 deletions
diff --git a/java/010ExcludeList b/java/010ExcludeList
index 59a4a0097c..813d4ada35 100644
--- a/java/010ExcludeList
+++ b/java/010ExcludeList
@@ -4,6 +4,7 @@ org.apache.qpid.client.ResetMessageListenerTest#*
org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveC2Only
org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveBoth
org.apache.qpid.test.unit.xa.TopicTest#testMigrateDurableSubscriber
+org.apache.qpid.test.unit.ack.AcknowledgeTest#*
// those tests need durable subscribe states to be persisted
org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testDurSubRestoredAfterNonPersistentMessageSent
// those tests require broker recovery
@@ -32,6 +33,7 @@ org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
org.apache.qpid.test.testcases.FailoverTest#*
+org.apache.qpid.test.client.failover.FailoverTest#*
// Those tests are testing 0.8 specific semantics
org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P
org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P
@@ -45,5 +47,19 @@ org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFails
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxP2P
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteNoTxPubSub
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxPubSub
+org.apache.qpid.test.client.FlowControlTest#*
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testDefaultExchanges
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnresolvedVirtualHostFailure
// the 0.10 c++ broker does not implement forget
-org.apache.qpid.test.unit.xa.FaultTest#testForget \ No newline at end of file
+org.apache.qpid.test.unit.xa.FaultTest#testForget
+// the 0-10 c++ broker does not implement priority / this test depends on a Java broker extension for queue creation
+org.apache.qpid.server.queue.PriorityTest
+//this test checks explicitly for 0-8 flow control semantics
+org.apache.qpid.test.client.FlowControlTest
+// 0-10 c++ broker doesn't implement virtual hosts, or those wackhy exchanges
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnresolvedVirtualHostFailure
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testDefaultExchanges
+// 0-10 c++ broker in cpp.testprofile is started with no auth so won't pass this test
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testPasswordFailureConnection
+// c++ broker doesn't do selectors, so this will fail
+org.apache.qpid.test.unit.topic.TopicSessionTest#testNonMatchingMessagesDoNotFillQueue
diff --git a/java/010ExcludeList-noPrefetch b/java/010ExcludeList-noPrefetch
new file mode 100644
index 0000000000..610e31717a
--- /dev/null
+++ b/java/010ExcludeList-noPrefetch
@@ -0,0 +1,55 @@
+org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#*
+org.apache.qpid.client.ResetMessageListenerTest#*
+org.apache.qpid.test.unit.transacted.TransactedTest#testRollback
+// those tests need durable subscribe states to be persisted
+org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testDurSubRestoredAfterNonPersistentMessageSent
+org.apache.qpid.test.unit.ct.DurableSubscriberTest#testDurSubRestoresMessageSelector
+// This test cannot be run with no-prefetch
+org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash
+//These tests are for the java broker
+org.apache.qpid.server.security.acl.SimpleACLTest#*
+org.apache.qpid.server.plugins.PluginTest#*
+// This test is not finished
+org.apache.qpid.test.testcases.TTLTest#*
+// Those tests require failover support
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.testcases.FailoverTest#*
+org.apache.qpid.test.client.failover.FailoverTest#*
+// Those tests are testing 0.8 specific semantics
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsNoRouteNoTxP2P
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsNoRouteTxP2P
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsNoRouteNoTxPubSub
+org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsNoRouteTxPubSub
+org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteNoTxP2P
+org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxP2P
+org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteNoTxPubSub
+org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxPubSub
+org.apache.qpid.test.client.FlowControlTest#*
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testDefaultExchanges
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnresolvedVirtualHostFailure
+// the 0.10 c++ broker does not implement forget
+org.apache.qpid.test.unit.xa.FaultTest#testForget
+// the 0-10 c++ broker does not implement priority / this test depends on a Java broker extension for queue creation
+org.apache.qpid.server.queue.PriorityTest
+//this test checks explicitly for 0-8 flow control semantics
+org.apache.qpid.test.client.FlowControlTest
+// The default cpp.testprofile does not start the cpp broker with authentication so this test will fail.
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testPasswordFailureConnection
+// c++ broker doesn't do selectors, so this will fail
+org.apache.qpid.test.unit.topic.TopicSessionTest#testNonMatchingMessagesDoNotFillQueue
+
diff --git a/java/010ExcludeList-store b/java/010ExcludeList-store
index ccd47ce58b..1ff2b4bbc6 100644
--- a/java/010ExcludeList-store
+++ b/java/010ExcludeList-store
@@ -5,6 +5,7 @@ org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveC2Only
org.apache.qpid.client.MessageListenerMultiConsumerTest#testRecieveBoth
org.apache.qpid.test.unit.xa.TopicTest#testMultiMessagesDurSubCrash
org.apache.qpid.test.unit.xa.TopicTest#testMigrateDurableSubscriber
+org.apache.qpid.test.unit.ack.AcknowledgeTest#*
// those tests need durable subscribe states to be persisted
org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testDurSubRestoredAfterNonPersistentMessageSent
org.apache.qpid.test.unit.ct.DurableSubscriberTest#testDurSubRestoresMessageSelector
@@ -27,6 +28,7 @@ org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
org.apache.qpid.test.testcases.FailoverTest#*
+org.apache.qpid.test.client.failover.FailoverTest#*
// Those tests are testing 0.8 specific semantics
org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P
org.apache.qpid.test.testcases.ImmediateMessageTest#test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P
@@ -40,5 +42,16 @@ org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFails
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxP2P
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteNoTxPubSub
org.apache.qpid.test.testcases.MandatoryMessageTest#test_QPID_508_MandatoryFailsNoRouteTxPubSub
+org.apache.qpid.test.client.FlowControlTest#*
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testDefaultExchanges
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testUnresolvedVirtualHostFailure
// the 0.10 c++ broker does not implement forget
-org.apache.qpid.test.unit.xa.FaultTest#testForget \ No newline at end of file
+org.apache.qpid.test.unit.xa.FaultTest#testForget
+// the 0-10 c++ broker does not implement priority / this test depends on a Java broker extension for queue creation
+org.apache.qpid.server.queue.PriorityTest
+//this test checks explicitly for 0-8 flow control semantics
+org.apache.qpid.test.client.FlowControlTest
+// The default cpp.testprofile does not start the cpp broker with authentication so this test will fail.
+org.apache.qpid.test.unit.client.connection.ConnectionTest#testPasswordFailureConnection
+// c++ broker doesn't do selectors, so this will fail
+org.apache.qpid.test.unit.topic.TopicSessionTest#testNonMatchingMessagesDoNotFillQueue
diff --git a/java/08ExcludeList b/java/08ExcludeList
index bd0d9a37e1..a3caba4df3 100644
--- a/java/08ExcludeList
+++ b/java/08ExcludeList
@@ -2,7 +2,8 @@ org.apache.qpid.test.unit.xa.QueueTest#*
org.apache.qpid.test.unit.xa.TopicTest#*
org.apache.qpid.test.unit.xa.FaultTest#*
org.apache.qpid.test.unit.ct.DurableSubscriberTests#*
-org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testDurableWithInvalidSelector
// Those tests are not finished
org.apache.qpid.test.testcases.TTLTest#*
org.apache.qpid.test.testcases.FailoverTest#*
+// This is a long running test so should exclude from normal runs
+org.apache.qpid.test.client.failover.FailoverTest#test4MinuteFailover
diff --git a/java/08ExcludeList-nonvm b/java/08ExcludeList-nonvm
new file mode 100644
index 0000000000..d377824c09
--- /dev/null
+++ b/java/08ExcludeList-nonvm
@@ -0,0 +1,24 @@
+org.apache.qpid.test.unit.xa.QueueTest#*
+org.apache.qpid.test.unit.xa.TopicTest#*
+org.apache.qpid.test.unit.xa.FaultTest#*
+org.apache.qpid.test.unit.ct.DurableSubscriberTests#*
+// Those tests are not finished
+org.apache.qpid.test.testcases.TTLTest#*
+org.apache.qpid.test.testcases.FailoverTest#*
+// This is a long running test so should exclude from normal runs
+org.apache.qpid.test.client.failover.FailoverTest#test4MinuteFailover
+// Those tests require failover support
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserAutoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserClientAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserDupsOkTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserNoAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserPreAckTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverAsQueueBrowserCreated
+org.apache.qpid.test.client.QueueBrowserTransactedTest#testFailoverWithQueueBrowser
+org.apache.qpid.test.testcases.FailoverTest#*
+org.apache.qpid.test.client.failover.FailoverTest#*
diff --git a/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java b/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
index 77cc12df7c..027d220538 100644
--- a/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
+++ b/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/diagnostic/DiagnosticExchange.java
@@ -22,6 +22,8 @@ package org.apache.qpid.extras.exchanges.diagnostic;
import java.util.List;
import java.util.Map;
+import java.util.ArrayList;
+import java.util.Collection;
import javax.management.JMException;
import javax.management.openmbean.OpenDataException;
@@ -34,7 +36,7 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.AbstractExchange;
import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.junit.extensions.util.SizeOf;
@@ -191,7 +193,7 @@ public class DiagnosticExchange extends AbstractExchange
return false;
}
- public void route(AMQMessage payload) throws AMQException
+ public void route(IncomingMessage payload) throws AMQException
{
Long value = new Long(SizeOf.getUsedMemory());
@@ -201,17 +203,14 @@ public class DiagnosticExchange extends AbstractExchange
headers.put(key, value);
((BasicContentHeaderProperties)payload.getContentHeaderBody().properties).setHeaders(headers);
AMQQueue q = getQueueRegistry().getQueue(new AMQShortString("diagnosticqueue"));
-
- payload.enqueue(q);
+
+ ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
+ queues.add(q);
+ payload.enqueue(queues);
}
- @Override
- public Map<AMQShortString, List<AMQQueue>> getBindings() {
- // TODO Auto-generated method stub
- return null;
- }
-
+
public boolean isBound(AMQShortString routingKey, FieldTable arguments,
AMQQueue queue) {
// TODO Auto-generated method stub
diff --git a/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java b/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
index d56a958044..067125de56 100644
--- a/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
+++ b/java/broker-plugins/src/main/java/org/apache/qpid/extras/exchanges/example/TestExchange.java
@@ -1,24 +1,3 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
package org.apache.qpid.extras.exchanges.example;
import java.util.List;
@@ -28,7 +7,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -102,7 +81,7 @@ public class TestExchange implements Exchange
{
}
- public void route(AMQMessage message) throws AMQException
+ public void route(IncomingMessage message) throws AMQException
{
}
diff --git a/java/broker/bin/qpid-passwd b/java/broker/bin/qpid-passwd
index f046252522..f425eed72b 100644
--- a/java/broker/bin/qpid-passwd
+++ b/java/broker/bin/qpid-passwd
@@ -18,6 +18,11 @@
# under the License.
#
+if [ -z "$QPID_HOME" ]; then
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
+fi
+
# Set classpath to include Qpid jar with all required jars in manifest
QPID_LIBS=$QPID_HOME/lib/qpid-incubating.jar
diff --git a/java/broker/bin/qpid-server b/java/broker/bin/qpid-server
index d0198f8dc9..b8d6c8e3fd 100644
--- a/java/broker/bin/qpid-server
+++ b/java/broker/bin/qpid-server
@@ -18,6 +18,11 @@
# under the License.
#
+if [ -z "$QPID_HOME" ]; then
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
+fi
+
# Set classpath to include Qpid jar with all required jars in manifest
QPID_LIBS=$QPID_HOME/lib/qpid-incubating.jar:$QPID_HOME/lib/bdbstore-launch.jar
@@ -26,6 +31,7 @@ export JAVA=java \
JAVA_VM=-server \
JAVA_MEM=-Xmx1024m \
JAVA_GC="-XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError" \
- QPID_CLASSPATH=$QPID_LIBS
+ QPID_CLASSPATH=$QPID_LIBS \
+ QPID_RUN_LOG=2
. qpid-run org.apache.qpid.server.Main "$@"
diff --git a/java/broker/bin/qpid-server.bat b/java/broker/bin/qpid-server.bat
index a99022cd2d..6af214f939 100644
--- a/java/broker/bin/qpid-server.bat
+++ b/java/broker/bin/qpid-server.bat
@@ -17,7 +17,7 @@
@REM under the License.
@REM
-echo off
+@echo off
REM Script to run the Qpid Java Broker
rem Guess QPID_HOME if not defined
@@ -36,35 +36,168 @@ echo This environment variable is needed to run this program
goto end
:okHome
+REM set QPID_WORK if not set
+if not "%QPID_WORK%" == "" goto okQpidWork
+if "%HOME%" == "" goto noHome
+set QPID_WOKR=%HOME%
+goto okQpidWork
+
+:noHome
+set QPID_WORK=c:\Temp
+if not exist %QPID_WORK% md %QPID_WORK%
+:okQpidWork
+
if not "%JAVA_HOME%" == "" goto gotJavaHome
echo The JAVA_HOME environment variable is not defined
echo This environment variable is needed to run this program
-goto exit
+goto end
:gotJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
goto okJavaHome
:noJavaHome
echo The JAVA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program.
-goto exit
+goto end
:okJavaHome
-rem Slurp the command line arguments. This loop allows for an unlimited number
-rem of agruments (up to the command line limit, anyway).
-set QPID_ARGS=%1
-if ""%1""=="""" goto runCommand
-shift
-:loop
-if ""%1""=="""" goto runCommand
-set QPID_ARGS=%QPID_ARGS% %1
+REM set loggin level if not set
+if "%AMQJ_LOGGING_LEVEL%" == "" set AMQJ_LOGGING_LEVEL=info
+
+REM Set the default system properties that we'll use now that they have
+REM all been initialised
+set SYSTEM_PROPS=-Damqj.logging.level=%AMQJ_LOGGING_LEVEL% -DQPID_HOME=%QPID_HOME% -DQPID_WORK=%QPID_WORK%
+
+if "%EXTERNAL_CLASSPATH%" == "" set EXTERNAL_CLASSPATH=%CLASSPATH%
+
+REM Use QPID_CLASSPATH if set
+if "%QPID_CLASSPATH%" == "" goto noQpidClasspath
+set CLASSPATH=%QPID_CLASSPATH%
+echo Using CLASSPATH: %CLASSPATH%
+goto afterQpidClasspath
+
+:noQpidClasspath
+echo Warning: Qpid classpath not set. CLASSPATH set to %QPID_HOME%\lib\qpid-incubating.jar
+set CLASSPATH=%QPID_HOME%\lib\qpid-incubating.jar
+:afterQpidClasspath
+
+REM start parsing -run arguments
+set QPID_ARGS=
+if "%1" == "" goto endRunArgs
+:runLoop
+set var=%1
+if "%var:~0,5%" == "-run:" goto runFound
+set QPID_ARGS=%QPID_ARGS% %1
+:beforeRunShift
shift
-goto loop
+if not "%1"=="" goto runLoop
+goto endRunArgs
+
+:runFound
+if "%var%" == "-run:debug" goto runDebug
+if "%var%" == "-run:jpda" goto runJdpa
+if "%var:~0,24%" == "-run:external-classpath-" goto runExternalClasspath
+if "%var%" == "-run:print-classpath" goto runPrintCP
+if "%var%" == "-run:help" goto runHelp
+echo "unrecognized -run option '%var%'. For using external classpaths use -run:external-classpath-option"
+goto end
+
+:runDebug
+REM USAGE: print the classpath and command before running it
+set debug=true
+goto beforeRunShift
+
+:runJdpa
+REM USAGE: adds debugging options to the java command, use
+REM USAGE: JDPA_TRANSPORT and JPDA_ADDRESS to customize the debugging
+REM USAGE: behavior and use JPDA_OPTS to override it entirely
+if "%JPDA_OPTS%" == "" goto beforeRunShift
+if "%JPDA_TRANSPORT%" == "" set JPDA_TRANSPORT=-dt_socket
+if "%JPDA_ADDRESS%" == "" set JPDA_ADDRESS=8000
+set JPDA_OPTS="-Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n"
+set QPID_OPTS="%QPID_OPTS% %JPDA_OPTS%"
+goto beforeRunShift
+
+:runExternalClasspath
+echo Using external classpath %var%
+REM USAGE: Format is -run:external-classpath-first/last/ignore/only as equals special in DOS
+REM USAGE: controls how the CLASSPATH environment variable is used by
+REM USAGE: this script, value can be one of ignore (the default), first,
+REM USAGE: last, and only
+if "%var%" == "-run:external-classpath-ignore" goto beforeRunShift
+if "%var%" == "-run:external-classpath-first" goto extCPFirst
+if "%var%" == "-run:external-classpath-last" goto extCPLast
+if "%var%" == "-run:external-classpath-only" goto extCPOnly
+echo Invalid value provided for external classpath.
+goto end
+
+:extCPFirst
+set CLASSPATH=%EXTERNAL_CLASSPATH%;%CLASSPATH%
+goto beforeRunShift
+
+:extCPLast
+set CLASSPATH=%CLASSPATH%;%EXTERNAL_CLASSPATH%
+goto beforeRunShift
+
+:extCPonly
+set CLASSPATH=%EXTERNAL_CLASSPATH%
+goto beforeRunShift
+
+:runPrintCP
+REM USAGE: print the classpath
+echo %CLASSPATH%
+goto beforeRunShift
+
+:runHelp
+REM USAGE: print this message
+echo -------------------------------------------------------------------------------------------
+echo -run:option where option can be the following.
+echo debug : Prints classpath and command before running it
+echo jpda : Adds remote debugging info using JPDA_OPTS. Use JPDA_TRANSPORT and JPDA_ADDRESS to
+echo customize, JPDA_OPTS to override
+echo external-classpath : Valid values are: ignore, first, last and only.
+echo print-classpath : Prints classpath before running command
+echo help : Prints this message
+echo --------------------------------------------------------------------------------------------
+goto end
+
+REM end parsing -run arguments
+:endRunArgs
+
+set JAVA_VM=-server
+set JAVA_MEM=-Xmx1024m
+set JAVA_GC=-XX:+UseConcMarkSweepGC
+rem removing the following vm arg from JAVA_GC as it is supported on ly in Java 1.6
+rem -XX:+HeapDumpOnOutOfMemoryError"
+
+REM Use QPID_JAVA_GC if set
+if "%QPID_JAVA_GC%" == "" goto noQpidJavaGC
+set JAVA_GC=%QPID_JAVA_GC%
+echo Using QPID_JAVA_GC setting: %QPID_JAVA_GC%
+goto afteQpidJavaGC
+
+:noQPidJavaGC
+echo Info: QPID_JAVA_GC not set. Defaulting to JAVA_GC %JAVA_GC%
+:afterQpidJavaGC
+
+REM Use QPID_JAVA_MEM if set
+if "%QPID_JAVA_MEM%" == "" goto noQpidJavaMem
+set JAVA_MEM=%QPID_JAVA_MEM%
+echo Using QPID_JAVA_MEM setting: %QPID_JAVA_MEM%
+goto afterQpidJavaMem
+
+:noQpidJavaMem
+echo Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM %JAVA_MEM%
+:after QpidJavaMem
+
rem QPID_OPTS intended to hold any -D props for use
rem user must enclose any value for QPID_OPTS in double quotes
:runCommand
-set LAUNCH_JAR=%QPID_HOME%\lib\qpid-incubating.jar
set MODULE_JARS=%QPID_MODULE_JARS%
-"%JAVA_HOME%\bin\java" -server -Xmx1024m %QPID_OPTS% -DQPID_HOME="%QPID_HOME%" -cp "%LAUNCH_JAR%;%MODULE_JARS%" org.apache.qpid.server.Main %QPID_ARGS%
+set COMMAND="%JAVA_HOME%\bin\java" %JAVA_VM% %JAVA_MEM% %JAVA_GC% %QPID_OPTS% %SYSTEM_PROPS% -cp "%CLASSPATH%;%MODULE_JARS%" org.apache.qpid.server.Main %QPID_ARGS%
+
+if "%debug%" == "true" echo %CLASSPATH%;%LAUNCH_JAR%;%MODULE_JARS%
+if "%debug%" == "true" echo %COMMAND%
+%COMMAND%
:end
diff --git a/java/broker/etc/acl.config.xml b/java/broker/etc/acl.config.xml
index 73c8d239de..614ecf0a88 100644
--- a/java/broker/etc/acl.config.xml
+++ b/java/broker/etc/acl.config.xml
@@ -93,7 +93,7 @@
<queues>
<exchange>amq.direct</exchange>
<!-- 4Mb -->
- <maximumQueueDepth>4235g264</maximumQueueDepth>
+ <maximumQueueDepth>4235264</maximumQueueDepth>
<!-- 2Mb -->
<maximumMessageSize>2117632</maximumMessageSize>
<!-- 10 mins -->
diff --git a/java/broker/src/main/grammar/SelectorParser.jj b/java/broker/src/main/grammar/SelectorParser.jj
index eb4467f1cc..c9e01cd01f 100644
--- a/java/broker/src/main/grammar/SelectorParser.jj
+++ b/java/broker/src/main/grammar/SelectorParser.jj
@@ -94,7 +94,7 @@ public class SelectorParser {
return this.JmsSelector();
}
catch (Throwable e) {
- throw (AMQInvalidArgumentException)new AMQInvalidArgumentException(sql, e);
+ throw (AMQInvalidArgumentException)new AMQInvalidArgumentException(sql,e);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
index 9335723bc5..88d5360f3e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -56,8 +56,9 @@ import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
import org.apache.qpid.server.management.ManagedBroker;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -175,7 +176,8 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
ownerShortString = new AMQShortString(owner);
}
- queue = new AMQQueue(new AMQShortString(queueName), durable, ownerShortString, false, getVirtualHost());
+ queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), durable, ownerShortString, false, getVirtualHost(),
+ null);
if (queue.isDurable() && !queue.isAutoDelete())
{
_messageStore.createQueue(queue);
@@ -220,7 +222,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
try
{
queue.delete();
- _messageStore.removeQueue(new AMQShortString(queueName));
+ _messageStore.removeQueue(queue);
}
catch (AMQException ex)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index 1314b2b715..847c8b8459 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server;
import org.apache.log4j.Logger;
-
import org.apache.qpid.AMQException;
import org.apache.qpid.configuration.Configured;
import org.apache.qpid.framing.AMQShortString;
@@ -30,14 +29,23 @@ import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.ack.UnacknowledgedMessage;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl;
import org.apache.qpid.server.configuration.Configurator;
-import org.apache.qpid.server.exchange.NoRouteException;
import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.exchange.NoRouteException;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.*;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.IncomingMessage;
+import org.apache.qpid.server.queue.MessageHandleFactory;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
+import org.apache.qpid.server.subscription.ClientDeliveryMethod;
+import org.apache.qpid.server.subscription.RecordDeliveryMethod;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.txn.LocalTransactionalContext;
@@ -45,13 +53,13 @@ import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.txn.TransactionalContext;
import java.util.Collection;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
public class AMQChannel
{
@@ -61,13 +69,8 @@ public class AMQChannel
private final int _channelId;
- // private boolean _transactional;
-
- private long _prefetch_HighWaterMark;
- private long _prefetch_LowWaterMark;
-
- private long _prefetchSize;
+ private final Pre0_10CreditManager _creditManager = new Pre0_10CreditManager(0l,0l);
/**
* The delivery tag is unique per channel. This is pre-incremented before putting into the deliver frame so that
@@ -86,10 +89,11 @@ public class AMQChannel
* been received by this channel. As the frames are received the message gets updated and once all frames have been
* received the message can then be routed.
*/
- private AMQMessage _currentMessage;
+ private IncomingMessage _currentMessage;
+
+ /** Maps from consumer tag to subscription instance. Allows us to unsubscribe from a queue. */
+ private final Map<AMQShortString, Subscription> _tag2SubscriptionMap = new HashMap<AMQShortString, Subscription>();
- /** Maps from consumer tag to queue instance. Allows us to unsubscribe from a queue. */
- private final Map<AMQShortString, AMQQueue> _consumerTag2QueueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>();
private final MessageStore _messageStore;
@@ -97,7 +101,7 @@ public class AMQChannel
private final AtomicBoolean _suspended = new AtomicBoolean(false);
- private TransactionalContext _txnContext, _nonTransactedContext;
+ private TransactionalContext _txnContext;
/**
* A context used by the message store enabling it to track context for a given channel even across thread
@@ -109,8 +113,6 @@ public class AMQChannel
private MessageHandleFactory _messageHandleFactory = new MessageHandleFactory();
- private Set<Long> _browsedAcks = new HashSet<Long>();
-
// Why do we need this reference ? - ritchiem
private final AMQProtocolSession _session;
private boolean _closing;
@@ -118,7 +120,7 @@ public class AMQChannel
@Configured(path = "advanced.enableJMSXUserID",
defaultValue = "false")
public boolean ENABLE_JMSXUserID;
-
+
public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore)
throws AMQException
@@ -129,8 +131,8 @@ public class AMQChannel
_session = session;
_channelId = channelId;
_storeContext = new StoreContext("Session: " + session.getClientIdentifier() + "; channel: " + channelId);
- _prefetch_HighWaterMark = DEFAULT_PREFETCH;
- _prefetch_LowWaterMark = _prefetch_HighWaterMark / 2;
+
+
_messageStore = messageStore;
// by default the session is non-transactional
@@ -140,7 +142,7 @@ public class AMQChannel
/** Sets this channel to be part of a local transaction */
public void setLocalTransactional()
{
- _txnContext = new LocalTransactionalContext(_messageStore, _storeContext, _returnMessages);
+ _txnContext = new LocalTransactionalContext(this);
}
public boolean isTransactional()
@@ -156,55 +158,15 @@ public class AMQChannel
return _channelId;
}
- public long getPrefetchCount()
- {
- return _prefetch_HighWaterMark;
- }
-
- public void setPrefetchCount(long prefetchCount)
- {
- _prefetch_HighWaterMark = prefetchCount;
- }
-
- public long getPrefetchSize()
- {
- return _prefetchSize;
- }
-
- public void setPrefetchSize(long prefetchSize)
- {
- _prefetchSize = prefetchSize;
- }
-
- public long getPrefetchLowMarkCount()
- {
- return _prefetch_LowWaterMark;
- }
-
- public void setPrefetchLowMarkCount(long prefetchCount)
- {
- _prefetch_LowWaterMark = prefetchCount;
- }
-
- public long getPrefetchHighMarkCount()
- {
- return _prefetch_HighWaterMark;
- }
-
- public void setPrefetchHighMarkCount(long prefetchCount)
- {
- _prefetch_HighWaterMark = prefetchCount;
- }
-
- public void setPublishFrame(MessagePublishInfo info, AMQProtocolSession publisher, final Exchange e) throws AMQException
+ public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQException
{
- _currentMessage = new AMQMessage(_messageStore.getNewMessageId(), info, _txnContext);
- _currentMessage.setPublisher(publisher);
+ _currentMessage = new IncomingMessage(_messageStore.getNewMessageId(), info, _txnContext, _session);
+ _currentMessage.setMessageStore(_messageStore);
_currentMessage.setExchange(e);
}
- public void publishContentHeader(ContentHeaderBody contentHeaderBody, AMQProtocolSession protocolSession)
+ public void publishContentHeader(ContentHeaderBody contentHeaderBody)
throws AMQException
{
if (_currentMessage == null)
@@ -215,7 +177,7 @@ public class AMQChannel
{
if (_log.isDebugEnabled())
{
- _log.debug(debugIdentity() + "Content header received on channel " + _channelId);
+ _log.debug("Content header received on channel " + _channelId);
}
if (ENABLE_JMSXUserID)
@@ -225,25 +187,48 @@ public class AMQChannel
//fixme: fudge for QPID-677
properties.getHeaders().keySet();
- properties.setUserId(protocolSession.getAuthorizedID().getName());
+ properties.setUserId(_session.getAuthorizedID().getName());
}
_currentMessage.setContentHeaderBody(contentHeaderBody);
+
_currentMessage.setExpiration();
routeCurrentMessage();
- _currentMessage.routingComplete(_messageStore, _storeContext, _messageHandleFactory);
- // check and deliver if header says body length is zero
- if (contentHeaderBody.bodySize == 0)
+ _currentMessage.routingComplete(_messageStore, _messageHandleFactory);
+
+ deliverCurrentMessageIfComplete();
+
+ }
+ }
+
+ private void deliverCurrentMessageIfComplete()
+ throws AMQException
+ {
+ // check and deliver if header says body length is zero
+ if (_currentMessage.allContentReceived())
+ {
+ try
{
- _txnContext.messageProcessed(protocolSession);
+ _currentMessage.deliverToQueues();
+ }
+ catch (NoRouteException e)
+ {
+ _returnMessages.add(e);
+ }
+ finally
+ {
+ // callback to allow the context to do any post message processing
+ // primary use is to allow message return processing in the non-tx case
+ _txnContext.messageProcessed(_session);
_currentMessage = null;
}
}
+
}
- public void publishContentBody(ContentBody contentBody, AMQProtocolSession protocolSession) throws AMQException
+ public void publishContentBody(ContentBody contentBody) throws AMQException
{
if (_currentMessage == null)
{
@@ -260,15 +245,11 @@ public class AMQChannel
// returns true iff the message was delivered (i.e. if all data was
// received
- if (_currentMessage.addContentBodyFrame(_storeContext,
- protocolSession.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(
- contentBody)))
- {
- // callback to allow the context to do any post message processing
- // primary use is to allow message return processing in the non-tx case
- _txnContext.messageProcessed(protocolSession);
- _currentMessage = null;
- }
+ _currentMessage.addContentBodyFrame(
+ _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(
+ contentBody));
+
+ deliverCurrentMessageIfComplete();
}
catch (AMQException e)
{
@@ -287,6 +268,7 @@ public class AMQChannel
}
catch (NoRouteException e)
{
+ //_currentMessage.incrementReference();
_returnMessages.add(e);
}
}
@@ -307,18 +289,17 @@ public class AMQChannel
*
* @param tag the tag chosen by the client (if null, server will generate one)
* @param queue the queue to subscribe to
- * @param session the protocol session of the subscriber
- * @param noLocal Flag stopping own messages being receivied.
- * @param exclusive Flag requesting exclusive access to the queue
* @param acks Are acks enabled for this subscriber
* @param filters Filters to apply to this subscriber
*
+ * @param noLocal Flag stopping own messages being receivied.
+ * @param exclusive Flag requesting exclusive access to the queue
* @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests
*
* @throws ConsumerTagNotUniqueException if the tag is not unique
* @throws AMQException if something goes wrong
*/
- public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, AMQProtocolSession session, boolean acks,
+ public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks,
FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException, ConsumerTagNotUniqueException
{
if (tag == null)
@@ -326,77 +307,65 @@ public class AMQChannel
tag = new AMQShortString("sgen_" + getNextConsumerTag());
}
- if (_consumerTag2QueueMap.containsKey(tag))
+ if (_tag2SubscriptionMap.containsKey(tag))
{
throw new ConsumerTagNotUniqueException();
}
+ Subscription subscription =
+ SubscriptionFactoryImpl.INSTANCE.createSubscription(_channelId, _session, tag, acks, filters, noLocal, _creditManager);
+
+
+ // So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
// We add before we register as the Async Delivery process may AutoClose the subscriber
// so calling _cT2QM.remove before we have done put which was after the register succeeded.
// So to keep things straight we put before the call and catch all exceptions from the register and tidy up.
- _consumerTag2QueueMap.put(tag, queue);
+
+ _tag2SubscriptionMap.put(tag, subscription);
try
{
- queue.registerProtocolSession(session, _channelId, tag, acks, filters, noLocal, exclusive);
+ queue.registerSubscription(subscription, exclusive);
}
catch (AMQException e)
{
- _consumerTag2QueueMap.remove(tag);
+ _tag2SubscriptionMap.remove(tag);
throw e;
}
-
return tag;
}
/**
* Unsubscribe a consumer from a queue.
- * @param session
* @param consumerTag
* @return true if the consumerTag had a mapped queue that could be unregistered.
* @throws AMQException
*/
- public boolean unsubscribeConsumer(AMQProtocolSession session, AMQShortString consumerTag) throws AMQException
+ public boolean unsubscribeConsumer(AMQShortString consumerTag) throws AMQException
{
- if (_log.isDebugEnabled())
- {
- _log.debug("Unacked Map Dump size:" + _unacknowledgedMessageMap.size());
- _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
- {
-
- public boolean callback(UnacknowledgedMessage message) throws AMQException
- {
- _log.debug(message);
-
- return true;
- }
- public void visitComplete()
- {
- }
- });
- }
-
- AMQQueue q = _consumerTag2QueueMap.remove(consumerTag);
- if (q != null)
+ Subscription sub = _tag2SubscriptionMap.remove(consumerTag);
+ if (sub != null)
{
- q.unregisterProtocolSession(session, _channelId, consumerTag);
+ sub.getQueue().unregisterSubscription(sub);
return true;
}
+ else
+ {
+ _log.warn("Attempt to unsubscribe consumer with tag '"+consumerTag+"' which is not registered.");
+ }
return false;
}
/**
* Called from the protocol session to close this channel and clean up. T
*
- * @param session The session to close
- *
* @throws AMQException if there is an error during closure
*/
- public void close(AMQProtocolSession session) throws AMQException
+ public void close() throws AMQException
{
_txnContext.rollback();
- unsubscribeAllConsumers(session);
+ unsubscribeAllConsumers();
try
{
requeue();
@@ -414,11 +383,11 @@ public class AMQChannel
_closing = closing;
}
- private void unsubscribeAllConsumers(AMQProtocolSession session) throws AMQException
+ private void unsubscribeAllConsumers() throws AMQException
{
if (_log.isInfoEnabled())
{
- if (!_consumerTag2QueueMap.isEmpty())
+ if (!_tag2SubscriptionMap.isEmpty())
{
_log.info("Unsubscribing all consumers on channel " + toString());
}
@@ -428,17 +397,19 @@ public class AMQChannel
}
}
- for (Map.Entry<AMQShortString, AMQQueue> me : _consumerTag2QueueMap.entrySet())
+ for (Map.Entry<AMQShortString, Subscription> me : _tag2SubscriptionMap.entrySet())
{
if (_log.isInfoEnabled())
{
_log.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString());
}
- me.getValue().unregisterProtocolSession(session, _channelId, me.getKey());
+ Subscription sub = me.getValue();
+
+ sub.getQueue().unregisterSubscription(sub);
}
- _consumerTag2QueueMap.clear();
+ _tag2SubscriptionMap.clear();
}
/**
@@ -447,9 +418,9 @@ public class AMQChannel
* @param entry the record of the message on the queue that was delivered
* @param deliveryTag the delivery tag used when delivering the message (see protocol spec for description of the
* delivery tag)
- * @param consumerTag The tag for the consumer that is to acknowledge this message.
+ * @param subscription The consumer that is to acknowledge this message.
*/
- public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, AMQShortString consumerTag)
+ public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription)
{
if (_log.isDebugEnabled())
{
@@ -462,16 +433,13 @@ public class AMQChannel
if (_log.isDebugEnabled())
{
_log.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag
- + ") with a queue(" + entry.getQueue() + ") for " + consumerTag);
+ + ") with a queue(" + entry.getQueue() + ") for " + subscription);
}
}
}
- synchronized (_unacknowledgedMessageMap.getLock())
- {
- _unacknowledgedMessageMap.add(deliveryTag, new UnacknowledgedMessage(entry, consumerTag, deliveryTag,_unacknowledgedMessageMap));
- checkSuspension();
- }
+ _unacknowledgedMessageMap.add(deliveryTag, entry);
+
}
private final String id = "(" + System.identityHashCode(this) + ")";
@@ -490,7 +458,7 @@ public class AMQChannel
public void requeue() throws AMQException
{
// we must create a new map since all the messages will get a new delivery tag when they are redelivered
- Collection<UnacknowledgedMessage> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages();
+ Collection<QueueEntry> messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages();
// Deliver these messages out of the transaction as their delivery was never
// part of the transaction only the receive.
@@ -505,13 +473,9 @@ public class AMQChannel
if (!(_txnContext instanceof NonTransactionalContext))
{
- // if (_nonTransactedContext == null)
- {
- _nonTransactedContext =
- new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
- }
- deliveryContext = _nonTransactedContext;
+ deliveryContext =
+ new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
}
else
{
@@ -519,22 +483,23 @@ public class AMQChannel
}
}
- for (UnacknowledgedMessage unacked : messagesToBeDelivered)
+ for (QueueEntry unacked : messagesToBeDelivered)
{
if (!unacked.isQueueDeleted())
{
- // Ensure message is released for redelivery
- unacked.entry.release();
-
// Mark message redelivered
unacked.getMessage().setRedelivered(true);
+ // Ensure message is released for redelivery
+ unacked.release();
+
// Deliver Message
- deliveryContext.deliver(unacked.entry, false);
+ deliveryContext.requeue(unacked);
- // Should we allow access To the DM to directy deliver the message?
- // As we don't need to check for Consumers or worry about incrementing the message count?
- // unacked.queue.getDeliveryManager().deliver(_storeContext, unacked.queue.getName(), unacked.message, false);
+ }
+ else
+ {
+ unacked.discard(_storeContext);
}
}
@@ -549,32 +514,29 @@ public class AMQChannel
*/
public void requeue(long deliveryTag) throws AMQException
{
- UnacknowledgedMessage unacked = _unacknowledgedMessageMap.remove(deliveryTag);
+ QueueEntry unacked = _unacknowledgedMessageMap.remove(deliveryTag);
if (unacked != null)
{
+ // Mark message redelivered
+ unacked.getMessage().setRedelivered(true);
// Ensure message is released for redelivery
if (!unacked.isQueueDeleted())
{
- unacked.entry.release();
+ unacked.release();
}
- // Mark message redelivered
- unacked.getMessage().setRedelivered(true);
// Deliver these messages out of the transaction as their delivery was never
// part of the transaction only the receive.
TransactionalContext deliveryContext;
if (!(_txnContext instanceof NonTransactionalContext))
{
- // if (_nonTransactedContext == null)
- {
- _nonTransactedContext =
+
+ deliveryContext =
new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
- }
- deliveryContext = _nonTransactedContext;
}
else
{
@@ -584,7 +546,7 @@ public class AMQChannel
if (!unacked.isQueueDeleted())
{
// Redeliver the messages to the front of the queue
- deliveryContext.deliver(unacked.entry, true);
+ deliveryContext.requeue(unacked);
// Deliver increments the message count but we have already deliverted this once so don't increment it again
// this was because deliver did an increment changed this.
}
@@ -592,11 +554,8 @@ public class AMQChannel
{
_log.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked.getMessage().debugIdentity()
+ "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message.");
- // _log.error("Requested requeue of message:" + deliveryTag +
- // " but no queue defined using DeadLetter queue:" + getDeadLetterQueue());
- //
- // deliveryContext.deliver(unacked.message, getDeadLetterQueue(), false);
- //
+
+ unacked.discard(_storeContext);
}
}
else
@@ -604,25 +563,6 @@ public class AMQChannel
_log.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists."
+ _unacknowledgedMessageMap.size());
- if (_log.isDebugEnabled())
- {
- _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
- {
- int count = 0;
-
- public boolean callback(UnacknowledgedMessage message) throws AMQException
- {
- _log.debug(
- (count++) + ": (" + message.getMessage().debugIdentity() + ")" + "[" + message.deliveryTag + "]");
-
- return false; // Continue
- }
-
- public void visitComplete()
- {
- }
- });
- }
}
}
@@ -636,8 +576,10 @@ public class AMQChannel
*/
public void resend(final boolean requeue) throws AMQException
{
- final List<UnacknowledgedMessage> msgToRequeue = new LinkedList<UnacknowledgedMessage>();
- final List<UnacknowledgedMessage> msgToResend = new LinkedList<UnacknowledgedMessage>();
+
+
+ final Map<Long, QueueEntry> msgToRequeue = new LinkedHashMap<Long, QueueEntry>();
+ final Map<Long, QueueEntry> msgToResend = new LinkedHashMap<Long, QueueEntry>();
if (_log.isDebugEnabled())
{
@@ -647,23 +589,25 @@ public class AMQChannel
// Process the Unacked-Map.
// Marking messages who still have a consumer for to be resent
// and those that don't to be requeued.
+
_unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
{
- public boolean callback(UnacknowledgedMessage message) throws AMQException
+ public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException
{
- AMQShortString consumerTag = message.consumerTag;
+
AMQMessage msg = message.getMessage();
msg.setRedelivered(true);
- if (consumerTag != null)
+ final Subscription subscription = message.getDeliveredSubscription();
+ if (subscription != null)
{
// Consumer exists
- if (_consumerTag2QueueMap.containsKey(consumerTag))
+ if (!subscription.isClosed())
{
- msgToResend.add(message);
+ msgToResend.put(deliveryTag, message);
}
else // consumer has gone
{
- msgToRequeue.add(message);
+ msgToRequeue.put(deliveryTag, message);
}
}
else
@@ -675,7 +619,7 @@ public class AMQChannel
{
if (requeue)
{
- msgToRequeue.add(message);
+ msgToRequeue.put(deliveryTag, message);
}
else
{
@@ -684,7 +628,8 @@ public class AMQChannel
}
else
{
- _log.info("Message.queue is null and no DeadLetter Queue so dropping message:" + message);
+ message.discard(_storeContext);
+ _log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message);
}
}
@@ -697,6 +642,8 @@ public class AMQChannel
}
});
+ _unacknowledgedMessageMap.clear();
+
// Process Messages to Resend
if (_log.isDebugEnabled())
{
@@ -710,9 +657,15 @@ public class AMQChannel
}
}
- for (UnacknowledgedMessage message : msgToResend)
+ for (Map.Entry<Long, QueueEntry> entry : msgToResend.entrySet())
{
+ QueueEntry message = entry.getValue();
+ long deliveryTag = entry.getKey();
+
+
+
AMQMessage msg = message.getMessage();
+ AMQQueue queue = message.getQueue();
// Our Java Client will always suspend the channel when resending!
// If the client has requested the messages be resent then it is
@@ -727,46 +680,20 @@ public class AMQChannel
// else
// {
// release to allow it to be delivered
- message.entry.release();
// Without any details from the client about what has been processed we have to mark
// all messages in the unacked map as redelivered.
msg.setRedelivered(true);
- Subscription sub = message.entry.getDeliveredSubscription();
+ Subscription sub = message.getDeliveredSubscription();
if (sub != null)
{
- // Get the lock so we can tell if the sub scription has closed.
- // will stop delivery to this subscription until the lock is released.
- // note: this approach would allow the use of a single queue if the
- // PreDeliveryQueue would allow head additions.
- // In the Java Qpid client we are suspended whilst doing this so it is all rather Mute..
- // needs guidance from AMQP WG Model SIG
- synchronized (sub.getSendLock())
+
+ if(!queue.resend(message, sub))
{
- if (sub.isClosed())
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Subscription(" + System.identityHashCode(sub)
- + ") closed during resend so requeuing message");
- }
- // move this message to requeue
- msgToRequeue.add(message);
- }
- else
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Requeuing " + msg.debugIdentity() + " for resend via sub:"
- + System.identityHashCode(sub));
- }
-
- sub.addToResendQueue(message.entry);
- _unacknowledgedMessageMap.remove(message.deliveryTag);
- }
- } // sync(sub.getSendLock)
+ msgToRequeue.put(deliveryTag, message);
+ }
}
else
{
@@ -777,7 +704,7 @@ public class AMQChannel
+ ")to prevent loss");
}
// move this message to requeue
- msgToRequeue.add(message);
+ msgToRequeue.put(deliveryTag, message);
}
} // for all messages
// } else !isSuspend
@@ -795,13 +722,9 @@ public class AMQChannel
TransactionalContext deliveryContext;
if (!(_txnContext instanceof NonTransactionalContext))
{
- if (_nonTransactedContext == null)
- {
- _nonTransactedContext =
- new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
- }
- deliveryContext = _nonTransactedContext;
+ deliveryContext =
+ new NonTransactionalContext(_messageStore, _storeContext, this, _returnMessages);
}
else
{
@@ -809,14 +732,17 @@ public class AMQChannel
}
// Process Messages to Requeue at the front of the queue
- for (UnacknowledgedMessage message : msgToRequeue)
+ for (Map.Entry<Long, QueueEntry> entry : msgToRequeue.entrySet())
{
- message.entry.release();
- message.entry.setRedelivered(true);
+ QueueEntry message = entry.getValue();
+ long deliveryTag = entry.getKey();
+
+ message.release();
+ message.setRedelivered(true);
- deliveryContext.deliver(message.entry, true);
+ deliveryContext.requeue(message);
- _unacknowledgedMessageMap.remove(message.deliveryTag);
+ _unacknowledgedMessageMap.remove(deliveryTag);
}
}
@@ -827,38 +753,47 @@ public class AMQChannel
*
* @param queue the queue that has been deleted
*
- * @throws org.apache.qpid.AMQException if there is an error processing the unacked messages
*/
- public void queueDeleted(final AMQQueue queue) throws AMQException
+ /* public void queueDeleted(final AMQQueue queue)
{
- _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
+ try
{
- public boolean callback(UnacknowledgedMessage message) throws AMQException
+ _unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
{
- if (message.getQueue() == queue)
+ public boolean callback(UnacknowledgedMessage message)
{
- try
+ if (message.getQueue() == queue)
{
- message.discard(_storeContext);
- message.setQueueDeleted(true);
+ try
+ {
+ message.discard(_storeContext);
+ message.setQueueDeleted(true);
+ }
+ catch (AMQException e)
+ {
+ _log.error(
+ "Error decrementing ref count on message " + message.getMessage().getMessageId() + ": " + e, e);
+ throw new RuntimeException(e);
+ }
}
- catch (AMQException e)
- {
- _log.error(
- "Error decrementing ref count on message " + message.getMessage().getMessageId() + ": " + e, e);
- }
+
+ return false;
}
- return false;
- }
+ public void visitComplete()
+ {
+ }
+ });
+ }
+ catch (AMQException e)
+ {
+ _log.error("Unexpected Error while handling deletion of queue", e);
+ throw new RuntimeException(e);
+ }
- public void visitComplete()
- {
- }
- });
}
-
+*/
/**
* Acknowledge one or more messages.
*
@@ -870,23 +805,7 @@ public class AMQChannel
*/
public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException
{
- synchronized (_unacknowledgedMessageMap.getLock())
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Unacked (PreAck) Size:" + _unacknowledgedMessageMap.size());
- }
-
- _unacknowledgedMessageMap.acknowledgeMessage(deliveryTag, multiple, _txnContext);
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Unacked (PostAck) Size:" + _unacknowledgedMessageMap.size());
- }
-
- }
-
- checkSuspension();
+ _unacknowledgedMessageMap.acknowledgeMessage(deliveryTag, multiple, _txnContext);
}
/**
@@ -899,43 +818,22 @@ public class AMQChannel
return _unacknowledgedMessageMap;
}
- private void checkSuspension()
- {
- boolean suspend;
-
- suspend =
- ((_prefetch_HighWaterMark != 0) && (_unacknowledgedMessageMap.size() >= _prefetch_HighWaterMark))
- || ((_prefetchSize != 0) && (_prefetchSize < _unacknowledgedMessageMap.getUnacknowledgeBytes()));
-
- setSuspended(suspend);
- }
public void setSuspended(boolean suspended)
{
- boolean isSuspended = _suspended.get();
- if (isSuspended && !suspended)
- {
- // Continue being suspended if we are above the _prefetch_LowWaterMark
- suspended = _unacknowledgedMessageMap.size() > _prefetch_LowWaterMark;
- }
boolean wasSuspended = _suspended.getAndSet(suspended);
if (wasSuspended != suspended)
{
if (wasSuspended)
{
- _log.debug("Unsuspending channel " + this);
// may need to deliver queued messages
- for (AMQQueue q : _consumerTag2QueueMap.values())
+ for (Subscription s : _tag2SubscriptionMap.values())
{
- q.deliverAsync();
+ s.getQueue().deliverAsync(s);
}
}
- else
- {
- _log.debug("Suspending channel " + this);
- }
}
}
@@ -961,12 +859,7 @@ public class AMQChannel
public String toString()
{
- StringBuilder sb = new StringBuilder(30);
- sb.append("Channel: id ").append(_channelId).append(", transaction mode: ").append(isTransactional());
- sb.append(", prefetch marks: ").append(_prefetch_LowWaterMark);
- sb.append("/").append(_prefetch_HighWaterMark);
-
- return sb.toString();
+ return "["+_session.toString()+":"+_channelId+"]";
}
public void setDefaultQueue(AMQQueue queue)
@@ -984,14 +877,14 @@ public class AMQChannel
return _storeContext;
}
- public void processReturns(AMQProtocolSession session) throws AMQException
+ public void processReturns() throws AMQException
{
if (!_returnMessages.isEmpty())
{
for (RequiredDeliveryException bouncedMessage : _returnMessages)
{
AMQMessage message = bouncedMessage.getAMQMessage();
- session.getProtocolOutputConverter().writeReturn(message, _channelId, bouncedMessage.getReplyCode().getCode(),
+ _session.getProtocolOutputConverter().writeReturn(message, _channelId, bouncedMessage.getReplyCode().getCode(),
new AMQShortString(bouncedMessage.getMessage()));
message.decrementReference(_storeContext);
@@ -1001,40 +894,68 @@ public class AMQChannel
}
}
- public boolean wouldSuspend(AMQMessage msg)
+
+ public TransactionalContext getTransactionalContext()
{
- if (isSuspended())
- {
- return true;
- }
- else
- {
- boolean willSuspend =
- ((_prefetch_HighWaterMark != 0) && ((_unacknowledgedMessageMap.size() + 1) > _prefetch_HighWaterMark));
- if (!willSuspend)
- {
- final long unackedSize = _unacknowledgedMessageMap.getUnacknowledgeBytes();
+ return _txnContext;
+ }
- willSuspend = (_prefetchSize != 0) && (unackedSize != 0) && (_prefetchSize < (msg.getSize() + unackedSize));
- }
+ public boolean isClosing()
+ {
+ return _closing;
+ }
- if (willSuspend)
- {
- setSuspended(true);
- }
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _session;
+ }
- return willSuspend;
- }
+ public FlowCreditManager getCreditManager()
+ {
+ return _creditManager;
+ }
+ public void setCredit(final long prefetchSize, final int prefetchCount)
+ {
+ _creditManager.setCreditLimits(prefetchSize, prefetchCount);
}
- public TransactionalContext getTransactionalContext()
+ public List<RequiredDeliveryException> getReturnMessages()
{
- return _txnContext;
+ return _returnMessages;
}
- public boolean isClosing()
+ public MessageStore getMessageStore()
{
- return _closing;
+ return _messageStore;
+ }
+
+ private final ClientDeliveryMethod _clientDeliveryMethod = new ClientDeliveryMethod()
+ {
+
+ public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ throws AMQException
+ {
+ getProtocolSession().getProtocolOutputConverter().writeDeliver(entry.getMessage(), getChannelId(), deliveryTag, sub.getConsumerTag());
+ }
+ };
+
+ public ClientDeliveryMethod getClientDeliveryMethod()
+ {
+ return _clientDeliveryMethod;
+ }
+
+ private final RecordDeliveryMethod _recordDeliveryMethod = new RecordDeliveryMethod()
+ {
+
+ public void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ {
+ addUnacknowledgedMessage(entry, deliveryTag, sub);
+ }
+ };
+
+ public RecordDeliveryMethod getRecordDeliveryMethod()
+ {
+ return _recordDeliveryMethod;
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java
index d8a8cfb6d1..8ad2ace1b2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -34,7 +34,6 @@ import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
-import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.common.FixedSizeByteBufferAllocator;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
import org.apache.mina.transport.socket.nio.SocketSessionConfig;
@@ -279,6 +278,12 @@ public class Main
ByteBuffer.setAllocator(new FixedSizeByteBufferAllocator());
}
+
+ if(connectorConfig.useBiasedWrites)
+ {
+ System.setProperty("org.apache.qpid.use_write_biased_pool","true");
+ }
+
int port = connectorConfig.port;
String portStr = commandLine.getOptionValue("p");
@@ -415,7 +420,8 @@ public class Main
bindAddress = new InetSocketAddress(InetAddress.getByAddress(parseIP(bindAddr)), port);
}
- acceptor.bind(bindAddress, handler, sconfig);
+ bind(acceptor, bindAddress, handler, sconfig);
+
//fixme qpid.AMQP should be using qpidproperties to get value
_brokerLogger.info("Qpid.AMQP listening on non-SSL address " + bindAddress);
}
@@ -426,7 +432,8 @@ public class Main
try
{
- acceptor.bind(new InetSocketAddress(connectorConfig.sslPort), handler, sconfig);
+ bind(acceptor, new InetSocketAddress(connectorConfig.sslPort), handler, sconfig);
+
//fixme qpid.AMQP should be using qpidproperties to get value
_brokerLogger.info("Qpid.AMQP listening on SSL port " + connectorConfig.sslPort);
@@ -449,6 +456,23 @@ public class Main
}
}
+ /**
+ * Ensure that any bound Acceptors are recorded in the registry so they can be closed later.
+ *
+ * @param acceptor
+ * @param bindAddress
+ * @param handler
+ * @param sconfig
+ *
+ * @throws IOException from the acceptor.bind command
+ */
+ private void bind(IoAcceptor acceptor, InetSocketAddress bindAddress, AMQPFastProtocolHandler handler, SocketAcceptorConfig sconfig) throws IOException
+ {
+ acceptor.bind(bindAddress, handler, sconfig);
+
+ ApplicationRegistry.getInstance().addAcceptor(bindAddress, acceptor);
+ }
+
public static void main(String[] args)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java b/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java
index d61bb8916a..3f1947d65a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/RequiredDeliveryException.java
@@ -39,19 +39,30 @@ import org.apache.qpid.server.queue.AMQMessage;
*/
public abstract class RequiredDeliveryException extends AMQException
{
- private final AMQMessage _amqMessage;
+ private AMQMessage _amqMessage;
public RequiredDeliveryException(String message, AMQMessage payload)
{
super(message);
+ setMessage(payload);
+ }
+
+
+ public RequiredDeliveryException(String message)
+ {
+ super(message);
+ }
+
+ public void setMessage(final AMQMessage payload)
+ {
+
// Increment the reference as this message is in the routing phase
// and so will have the ref decremented as routing fails.
// we need to keep this message around so we can return it in the
// handler. So increment here.
_amqMessage = payload.takeReference();
- // payload.incrementReference();
}
public AMQMessage getAMQMessage()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java b/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java
index 6ad704a5d8..db3a05eb52 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/ack/TxAck.java
@@ -22,11 +22,14 @@ package org.apache.qpid.server.ack;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
import java.util.ArrayList;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.txn.TxnOp;
+import org.apache.qpid.server.queue.QueueEntry;
/**
* A TxnOp implementation for handling accumulated acks
@@ -34,7 +37,7 @@ import org.apache.qpid.server.txn.TxnOp;
public class TxAck implements TxnOp
{
private final UnacknowledgedMessageMap _map;
- private final List <UnacknowledgedMessage> _unacked = new ArrayList<UnacknowledgedMessage>();
+ private final Map<Long, QueueEntry> _unacked = new HashMap<Long,QueueEntry>();
private List<Long> _individual;
private long _deliveryTag;
private boolean _multiple;
@@ -46,11 +49,12 @@ public class TxAck implements TxnOp
public void update(long deliveryTag, boolean multiple)
{
+ _unacked.clear();
if (!multiple)
{
if(_individual == null)
{
- _individual = new ArrayList<Long>();
+ _individual = new ArrayList<Long>();
}
//have acked a single message that is not part of
//the previously acked region so record
@@ -64,36 +68,29 @@ public class TxAck implements TxnOp
_deliveryTag = deliveryTag;
_multiple = true;
}
- _unacked.clear();
}
public void consolidate()
{
if(_unacked.isEmpty())
{
- consolidate(_unacked);
- }
-
- }
-
- private void consolidate(List<UnacknowledgedMessage> unacked)
- {
- //lookup all the unacked messages that have been acked in this transaction
- if (_multiple)
- {
- //get all the unacked messages for the accumulated
- //multiple acks
- _map.collect(_deliveryTag, true, unacked);
- }
- //get any unacked messages for individual acks outside the
- //range covered by multiple acks
- if(_individual != null)
- {
- for (Long tag : _individual)
+ //lookup all the unacked messages that have been acked in this transaction
+ if (_multiple)
{
- if(_deliveryTag < tag)
+ //get all the unacked messages for the accumulated
+ //multiple acks
+ _map.collect(_deliveryTag, true, _unacked);
+ }
+ if(_individual != null)
+ {
+ //get any unacked messages for individual acks outside the
+ //range covered by multiple acks
+ for (long tag : _individual)
{
- _map.collect(tag, false, unacked);
+ if(_deliveryTag < tag)
+ {
+ _map.collect(tag, false, _unacked);
+ }
}
}
}
@@ -101,12 +98,10 @@ public class TxAck implements TxnOp
public boolean checkPersistent() throws AMQException
{
-
-
consolidate();
//if any of the messages in unacked are persistent the txn
//buffer must be marked as persistent:
- for (UnacknowledgedMessage msg : _unacked)
+ for (QueueEntry msg : _unacked.values())
{
if (msg.getMessage().isPersistent())
{
@@ -119,7 +114,7 @@ public class TxAck implements TxnOp
public void prepare(StoreContext storeContext) throws AMQException
{
//make persistent changes, i.e. dequeue and decrementReference
- for (UnacknowledgedMessage msg : _unacked)
+ for (QueueEntry msg : _unacked.values())
{
//Message has been ack so discard it. This will dequeue and decrement the reference.
msg.discard(storeContext);
@@ -133,7 +128,7 @@ public class TxAck implements TxnOp
//in memory counter) so if we failed in prepare for full
//txn, this op will have to compensate by fixing the count
//in memory (persistent changes will be rolled back by store)
- for (UnacknowledgedMessage msg : _unacked)
+ for (QueueEntry msg : _unacked.values())
{
msg.getMessage().takeReference();
}
@@ -142,7 +137,7 @@ public class TxAck implements TxnOp
public void commit(StoreContext storeContext)
{
//remove the unacked messages from the channels map
- _map.remove(_unacked);
+ _map.remove(_unacked);
}
public void rollback(StoreContext storeContext)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java
deleted file mode 100644
index 0112d3b388..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessage.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.ack;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.StoreContext;
-
-public class UnacknowledgedMessage
-{
- public final QueueEntry entry;
- public final AMQShortString consumerTag;
- public final long deliveryTag;
-
- private boolean _queueDeleted;
- private final UnacknowledgedMessageMap _unacknowledgeMessageMap;
-
-
- public UnacknowledgedMessage(QueueEntry entry,
- AMQShortString consumerTag,
- long deliveryTag,
- final UnacknowledgedMessageMap unacknowledgedMessageMap)
- {
- this.entry = entry;
- this.consumerTag = consumerTag;
- this.deliveryTag = deliveryTag;
- _unacknowledgeMessageMap = unacknowledgedMessageMap;
- }
-
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("Q:");
- sb.append(entry.getQueue());
- sb.append(" M:");
- sb.append(entry.getMessage());
- sb.append(" CT:");
- sb.append(consumerTag);
- sb.append(" DT:");
- sb.append(deliveryTag);
-
- return sb.toString();
- }
-
- public void discard(StoreContext storeContext) throws AMQException
- {
- synchronized(_unacknowledgeMessageMap)
- {
- if(_unacknowledgeMessageMap.contains(deliveryTag))
- {
-
- if (entry.getQueue() != null)
- {
- entry.getQueue().dequeue(storeContext, entry);
- }
- //if the queue is null then the message is waiting to be acked, but has been removed.
- entry.getMessage().decrementReference(storeContext);
- }
- }
-
- }
-
- public AMQMessage getMessage()
- {
- return entry.getMessage();
- }
-
- public AMQQueue getQueue()
- {
- return entry.getQueue();
- }
-
- public void setQueueDeleted(boolean queueDeleted)
- {
- _queueDeleted = queueDeleted;
- }
-
- public boolean isQueueDeleted()
- {
- return _queueDeleted;
- }
-}
-
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
index 5b0f3cf5eb..c80a96f967 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java
@@ -23,41 +23,42 @@ package org.apache.qpid.server.ack;
import java.util.Collection;
import java.util.List;
import java.util.Set;
+import java.util.Map;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.txn.TransactionalContext;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.StoreContext;
public interface UnacknowledgedMessageMap
{
public interface Visitor
{
/**
- * @param message the message being iterated over
- * @return true to stop iteration, false to continue
+ * @param deliveryTag
+ *@param message the message being iterated over @return true to stop iteration, false to continue
* @throws AMQException
*/
- boolean callback(UnacknowledgedMessage message) throws AMQException;
+ boolean callback(final long deliveryTag, QueueEntry message) throws AMQException;
void visitComplete();
}
void visit(Visitor visitor) throws AMQException;
- Object getLock();
+ void add(long deliveryTag, QueueEntry message);
- void add(long deliveryTag, UnacknowledgedMessage message);
-
- void collect(Long deliveryTag, boolean multiple, List<UnacknowledgedMessage> msgs);
+ void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs);
boolean contains(long deliveryTag) throws AMQException;
- void remove(List<UnacknowledgedMessage> msgs);
-
- UnacknowledgedMessage remove(long deliveryTag);
+ void remove(Map<Long,QueueEntry> msgs);
- void drainTo(Collection<UnacknowledgedMessage> destination, long deliveryTag) throws AMQException;
+ QueueEntry remove(long deliveryTag);
- Collection<UnacknowledgedMessage> cancelAllMessages();
+ public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException;
+
+ Collection<QueueEntry> cancelAllMessages();
void acknowledgeMessage(long deliveryTag, boolean multiple, TransactionalContext txnContext) throws AMQException;
@@ -65,7 +66,7 @@ public interface UnacknowledgedMessageMap
void clear();
- UnacknowledgedMessage get(long deliveryTag);
+ QueueEntry get(long deliveryTag);
/**
* Get the set of delivery tags that are outstanding.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
index 5204f13e81..c567387662 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.server.ack;
+import org.apache.qpid.server.store.StoreContext;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -28,6 +29,10 @@ import java.util.Map;
import java.util.Set;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.txn.TransactionalContext;
public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
@@ -36,7 +41,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
private long _unackedSize;
- private Map<Long, UnacknowledgedMessage> _map;
+ private Map<Long, QueueEntry> _map;
private long _lastDeliveryTag;
@@ -45,10 +50,10 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
public UnacknowledgedMessageMapImpl(int prefetchLimit)
{
_prefetchLimit = prefetchLimit;
- _map = new LinkedHashMap<Long, UnacknowledgedMessage>(prefetchLimit);
+ _map = new LinkedHashMap<Long, QueueEntry>(prefetchLimit);
}
- public void collect(Long deliveryTag, boolean multiple, List<UnacknowledgedMessage> msgs)
+ public void collect(long deliveryTag, boolean multiple, Map<Long, QueueEntry> msgs)
{
if (multiple)
{
@@ -56,7 +61,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
else
{
- msgs.add(get(deliveryTag));
+ msgs.put(deliveryTag, get(deliveryTag));
}
}
@@ -69,26 +74,27 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public void remove(List<UnacknowledgedMessage> msgs)
+ public void remove(Map<Long,QueueEntry> msgs)
{
synchronized (_lock)
{
- for (UnacknowledgedMessage msg : msgs)
+ for (Long deliveryTag : msgs.keySet())
{
- remove(msg.deliveryTag);
+ remove(deliveryTag);
}
}
}
- public UnacknowledgedMessage remove(long deliveryTag)
+ public QueueEntry remove(long deliveryTag)
{
synchronized (_lock)
{
- UnacknowledgedMessage message = _map.remove(deliveryTag);
+ QueueEntry message = _map.remove(deliveryTag);
if(message != null)
{
_unackedSize -= message.getMessage().getSize();
+
}
return message;
@@ -99,21 +105,16 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
{
synchronized (_lock)
{
- Collection<UnacknowledgedMessage> currentEntries = _map.values();
- for (UnacknowledgedMessage msg : currentEntries)
+ Set<Map.Entry<Long, QueueEntry>> currentEntries = _map.entrySet();
+ for (Map.Entry<Long, QueueEntry> entry : currentEntries)
{
- visitor.callback(msg);
+ visitor.callback(entry.getKey().longValue(), entry.getValue());
}
visitor.visitComplete();
}
}
- public Object getLock()
- {
- return _lock;
- }
-
- public void add(long deliveryTag, UnacknowledgedMessage message)
+ public void add(long deliveryTag, QueueEntry message)
{
synchronized (_lock)
{
@@ -123,12 +124,12 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public Collection<UnacknowledgedMessage> cancelAllMessages()
+ public Collection<QueueEntry> cancelAllMessages()
{
synchronized (_lock)
{
- Collection<UnacknowledgedMessage> currentEntries = _map.values();
- _map = new LinkedHashMap<Long, UnacknowledgedMessage>(_prefetchLimit);
+ Collection<QueueEntry> currentEntries = _map.values();
+ _map = new LinkedHashMap<Long, QueueEntry>(_prefetchLimit);
_unackedSize = 0l;
return currentEntries;
}
@@ -160,14 +161,15 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public void drainTo(Collection<UnacknowledgedMessage> destination, long deliveryTag) throws AMQException
+ public void drainTo(long deliveryTag, StoreContext storeContext) throws AMQException
+
{
synchronized (_lock)
{
- Iterator<Map.Entry<Long, UnacknowledgedMessage>> it = _map.entrySet().iterator();
+ Iterator<Map.Entry<Long, QueueEntry>> it = _map.entrySet().iterator();
while (it.hasNext())
{
- Map.Entry<Long, UnacknowledgedMessage> unacked = it.next();
+ Map.Entry<Long, QueueEntry> unacked = it.next();
if (unacked.getKey() > deliveryTag)
{
@@ -176,10 +178,14 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
" When deliveryTag is:" + deliveryTag + "ES:" + _map.entrySet().toString());
}
+ //Message has been ack so discard it. This will dequeue and decrement the reference.
+ unacked.getValue().discard(storeContext);
+
it.remove();
+
_unackedSize -= unacked.getValue().getMessage().getSize();
- destination.add(unacked.getValue());
+
if (unacked.getKey() == deliveryTag)
{
break;
@@ -188,7 +194,7 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- public UnacknowledgedMessage get(long key)
+ public QueueEntry get(long key)
{
synchronized (_lock)
{
@@ -204,14 +210,14 @@ public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap
}
}
- private void collect(Long key, List<UnacknowledgedMessage> msgs)
+ private void collect(long key, Map<Long, QueueEntry> msgs)
{
synchronized (_lock)
{
- for (Map.Entry<Long, UnacknowledgedMessage> entry : _map.entrySet())
+ for (Map.Entry<Long, QueueEntry> entry : _map.entrySet())
{
- msgs.add(entry.getValue());
- if (entry.getKey().equals(key))
+ msgs.put(entry.getKey(),entry.getValue());
+ if (entry.getKey() == key)
{
break;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
index 8573902af4..bd3e5b1f72 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java
@@ -30,11 +30,13 @@ import org.apache.commons.configuration.XMLConfiguration;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -176,11 +178,22 @@ public class VirtualHostConfiguration
boolean durable = queueConfiguration.getBoolean("durable" ,false);
boolean autodelete = queueConfiguration.getBoolean("autodelete", false);
String owner = queueConfiguration.getString("owner", null);
+ FieldTable arguments = null;
+ Integer priorities = queueConfiguration.getInteger("priorities", null);
+ if(priorities != null && priorities.intValue() > 1)
+ {
+ if(arguments == null)
+ {
+ arguments = new FieldTable();
+ }
+ arguments.put(new AMQShortString("x-qpid-priorities"), priorities);
+ }
+
- queue = new AMQQueue(queueName,
+ queue = AMQQueueFactory.createAMQQueueImpl(queueName,
durable,
owner == null ? null : new AMQShortString(owner) /* These queues will have no owner */,
- autodelete /* Therefore autodelete makes no sence */, virtualHost);
+ autodelete /* Therefore autodelete makes no sence */, virtualHost, arguments);
if (queue.isDurable())
{
@@ -221,7 +234,7 @@ public class VirtualHostConfiguration
AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj));
- queue.bind(routingKey, null, exchange);
+ queue.bind(exchange, routingKey, null);
_logger.info("Queue '" + queue.getName() + "' bound to exchange:" + exchangeName + " RK:'" + routingKey + "'");
@@ -229,7 +242,7 @@ public class VirtualHostConfiguration
if(exchange != virtualHost.getExchangeRegistry().getDefaultExchange())
{
- queue.bind(queue.getName(), null, virtualHost.getExchangeRegistry().getDefaultExchange());
+ queue.bind(virtualHost.getExchangeRegistry().getDefaultExchange(), queue.getName(), null);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
new file mode 100644
index 0000000000..d287595e2d
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.connection;
+
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.protocol.AMQMinaProtocolSession;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.protocol.AMQConstant;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.List;
+
+public class ConnectionRegistry implements IConnectionRegistry
+{
+ private List<AMQProtocolSession> _registry = new CopyOnWriteArrayList<AMQProtocolSession>();
+
+ private VirtualHost _virtualHost;
+
+ public ConnectionRegistry(VirtualHost virtualHost)
+ {
+ _virtualHost = virtualHost;
+ }
+
+ public void initialise()
+ {
+
+ }
+
+ /** Close all of the currently open connections. */
+ public void close() throws AMQException
+ {
+ while (!_registry.isEmpty())
+ {
+ AMQProtocolSession connection = _registry.get(0);
+
+ connection.closeConnection(0, new AMQConnectionException(AMQConstant.INTERNAL_ERROR, "Broker is shutting down",
+ 0, 0,
+ connection.getProtocolOutputConverter().getProtocolMajorVersion(),
+ connection.getProtocolOutputConverter().getProtocolMinorVersion(),
+ (Throwable) null), true);
+ }
+ }
+
+ public void registerConnection(AMQProtocolSession connnection)
+ {
+ _registry.add(connnection);
+ }
+
+ public void deregisterConnection(AMQProtocolSession connnection)
+ {
+ _registry.remove(connnection);
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/StateListener.java b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
index df207a0a23..d64fde1c20 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/StateListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,13 +18,21 @@
* under the License.
*
*/
-package org.apache.qpid.client.state;
+package org.apache.qpid.server.connection;
+import org.apache.qpid.server.protocol.AMQMinaProtocolSession;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.AMQException;
-public interface StateListener
+public interface IConnectionRegistry
{
- void stateChanged(AMQState oldState, AMQState newState) throws AMQException;
- void error(Throwable t);
+ public void initialise();
+
+ public void close() throws AMQException;
+
+ public void registerConnection(AMQProtocolSession connnection);
+
+ public void deregisterConnection(AMQProtocolSession connnection);
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 9ebb893362..8d24626b73 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -191,9 +191,7 @@ public abstract class AbstractExchange implements Exchange, Managable
{
_exchangeMbean.unregister();
}
- }
-
- abstract public Map<AMQShortString, List<AMQQueue>> getBindings();
+ }
public String toString()
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
index 636aa7eb03..9d4c090971 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java
@@ -43,8 +43,8 @@ public class DefaultExchangeFactory implements ExchangeFactory
public DefaultExchangeFactory(VirtualHost host)
{
_host = host;
- registerExchangeType(DestNameExchange.TYPE);
- registerExchangeType(DestWildExchange.TYPE);
+ registerExchangeType(DirectExchange.TYPE);
+ registerExchangeType(TopicExchange.TYPE);
registerExchangeType(HeadersExchange.TYPE);
registerExchangeType(FanoutExchange.TYPE);
}
@@ -67,7 +67,7 @@ public class DefaultExchangeFactory implements ExchangeFactory
if (exchType == null)
{
- throw new AMQUnknownExchangeType("Unknown exchange type: " + type, null);
+ throw new AMQUnknownExchangeType("Unknown exchange type: " + type,null);
}
Exchange e = exchType.newInstance(_host, exchange, durable, ticket, autoDelete);
return e;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
index 98abf7977a..0ab8208d88 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java
@@ -25,6 +25,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.protocol.ExchangeInitialiser;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -121,9 +122,9 @@ public class DefaultExchangeRegistry implements ExchangeRegistry
* @param payload
* @throws AMQException if something goes wrong delivering data
*/
- public void routeContent(AMQMessage payload) throws AMQException
+ public void routeContent(IncomingMessage payload) throws AMQException
{
- final AMQShortString exchange = payload.getMessagePublishInfo().getExchange();
+ final AMQShortString exchange = payload.getExchange();
final Exchange exch = getExchange(exchange);
// there is a small window of opportunity for the exchange to be deleted in between
// the BasicPublish being received (where the exchange is validated) and the final
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java
deleted file mode 100644
index 6fa3686152..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.AMQShortStringTokenizer;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.management.MBeanConstructor;
-import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-public class DestWildExchange extends AbstractExchange
-{
-
- public static final ExchangeType<DestWildExchange> TYPE = new ExchangeType<DestWildExchange>()
- {
-
- public AMQShortString getName()
- {
- return ExchangeDefaults.TOPIC_EXCHANGE_CLASS;
- }
-
- public Class<DestWildExchange> getExchangeClass()
- {
- return DestWildExchange.class;
- }
-
- public DestWildExchange newInstance(VirtualHost host,
- AMQShortString name,
- boolean durable,
- int ticket,
- boolean autoDelete) throws AMQException
- {
- DestWildExchange exch = new DestWildExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
- return exch;
- }
-
- public AMQShortString getDefaultExchangeName()
- {
- return ExchangeDefaults.TOPIC_EXCHANGE_NAME;
- }
- };
-
-
- private static final Logger _logger = Logger.getLogger(DestWildExchange.class);
-
- private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _bindingKey2queues =
- new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
- private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _simpleBindingKey2queues =
- new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
- private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _wildCardBindingKey2queues =
- new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
-
- private static final byte TOPIC_SEPARATOR = (byte)'.';
- private static final AMQShortString TOPIC_SEPARATOR_AS_SHORTSTRING = new AMQShortString(".");
- private static final AMQShortString AMQP_STAR_TOKEN = new AMQShortString("*");
- private static final AMQShortString AMQP_HASH_TOKEN = new AMQShortString("#");
- private ConcurrentHashMap<AMQShortString, AMQShortString[]> _bindingKey2Tokenized =
- new ConcurrentHashMap<AMQShortString, AMQShortString[]>();
- private static final byte HASH_BYTE = (byte)'#';
- private static final byte STAR_BYTE = (byte)'*';
-
- /** DestWildExchangeMBean class implements the management interface for the Topic exchanges. */
- @MBeanDescription("Management Bean for Topic Exchange")
- private final class DestWildExchangeMBean extends ExchangeMBean
- {
- @MBeanConstructor("Creates an MBean for AMQ topic exchange")
- public DestWildExchangeMBean() throws JMException
- {
- super();
- _exchangeType = "topic";
- init();
- }
-
- /** returns exchange bindings in tabular form */
- public TabularData bindings() throws OpenDataException
- {
- _bindingList = new TabularDataSupport(_bindinglistDataType);
- for (Map.Entry<AMQShortString, List<AMQQueue>> entry : _bindingKey2queues.entrySet())
- {
- AMQShortString key = entry.getKey();
- List<String> queueList = new ArrayList<String>();
-
- List<AMQQueue> queues = getMatchedQueues(key);
- for (AMQQueue q : queues)
- {
- queueList.add(q.getName().toString());
- }
-
- Object[] bindingItemValues = {key.toString(), queueList.toArray(new String[0])};
- CompositeData bindingData = new CompositeDataSupport(_bindingDataType, _bindingItemNames, bindingItemValues);
- _bindingList.put(bindingData);
- }
-
- return _bindingList;
- }
-
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange.");
- }
-
- try
- {
- queue.bind(new AMQShortString(binding), null, DestWildExchange.this);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex);
- }
- }
-
- } // End of MBean class
-
- public AMQShortString getType()
- {
- return ExchangeDefaults.TOPIC_EXCHANGE_CLASS;
- }
-
- public synchronized void registerQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- assert queue != null;
- assert rKey != null;
-
- _logger.debug("Registering queue " + queue.getName() + " with routing key " + rKey);
-
- // we need to use putIfAbsent, which is an atomic operation, to avoid a race condition
- List<AMQQueue> queueList = _bindingKey2queues.putIfAbsent(rKey, new CopyOnWriteArrayList<AMQQueue>());
-
-
-
-
-
-
-
- // if we got null back, no previous value was associated with the specified routing key hence
- // we need to read back the new value just put into the map
- if (queueList == null)
- {
- queueList = _bindingKey2queues.get(rKey);
- }
-
-
-
- if (!queueList.contains(queue))
- {
- queueList.add(queue);
-
-
- if(rKey.contains(HASH_BYTE) || rKey.contains(STAR_BYTE))
- {
- AMQShortString routingKey = normalize(rKey);
- List<AMQQueue> queueList2 = _wildCardBindingKey2queues.putIfAbsent(routingKey, new CopyOnWriteArrayList<AMQQueue>());
-
- if(queueList2 == null)
- {
- queueList2 = _wildCardBindingKey2queues.get(routingKey);
- AMQShortStringTokenizer keyTok = routingKey.tokenize(TOPIC_SEPARATOR);
-
- ArrayList<AMQShortString> keyTokList = new ArrayList<AMQShortString>(keyTok.countTokens());
-
- while (keyTok.hasMoreTokens())
- {
- keyTokList.add(keyTok.nextToken());
- }
-
- _bindingKey2Tokenized.put(routingKey, keyTokList.toArray(new AMQShortString[keyTokList.size()]));
- }
- queueList2.add(queue);
-
- }
- else
- {
- List<AMQQueue> queueList2 = _simpleBindingKey2queues.putIfAbsent(rKey, new CopyOnWriteArrayList<AMQQueue>());
- if(queueList2 == null)
- {
- queueList2 = _simpleBindingKey2queues.get(rKey);
- }
- queueList2.add(queue);
-
- }
-
-
-
-
- }
- else if (_logger.isDebugEnabled())
- {
- _logger.debug("Queue " + queue + " is already registered with routing key " + rKey);
- }
-
-
-
- }
-
- private AMQShortString normalize(AMQShortString routingKey)
- {
- if(routingKey == null)
- {
- routingKey = AMQShortString.EMPTY_STRING;
- }
-
- AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR);
-
- List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>();
-
- while (routingTokens.hasMoreTokens())
- {
- subscriptionList.add(routingTokens.nextToken());
- }
-
- int size = subscriptionList.size();
-
- for (int index = 0; index < size; index++)
- {
- // if there are more levels
- if ((index + 1) < size)
- {
- if (subscriptionList.get(index).equals(AMQP_HASH_TOKEN))
- {
- if (subscriptionList.get(index + 1).equals(AMQP_HASH_TOKEN))
- {
- // we don't need #.# delete this one
- subscriptionList.remove(index);
- size--;
- // redo this normalisation
- index--;
- }
-
- if (subscriptionList.get(index + 1).equals(AMQP_STAR_TOKEN))
- {
- // we don't want #.* swap to *.#
- // remove it and put it in at index + 1
- subscriptionList.add(index + 1, subscriptionList.remove(index));
- }
- }
- } // if we have more levels
- }
-
-
-
- AMQShortString normalizedString = AMQShortString.join(subscriptionList, TOPIC_SEPARATOR_AS_SHORTSTRING);
-
- return normalizedString;
- }
-
- public void route(AMQMessage payload) throws AMQException
- {
- MessagePublishInfo info = payload.getMessagePublishInfo();
-
- final AMQShortString routingKey = info.getRoutingKey();
-
- List<AMQQueue> queues = getMatchedQueues(routingKey);
- // if we have no registered queues we have nothing to do
- // TODO: add support for the immediate flag
- if ((queues == null) || queues.isEmpty())
- {
- if (info.isMandatory() || info.isImmediate())
- {
- String msg = "Topic " + routingKey + " is not known to " + this;
- throw new NoRouteException(msg, payload);
- }
- else
- {
- _logger.warn("No queues found for routing key " + routingKey);
- _logger.warn("Routing map contains: " + _bindingKey2queues);
-
- return;
- }
- }
-
- payload.enqueue(queues);
-
- }
-
- public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
- {
- return isBound(routingKey, queue);
- }
-
- public boolean isBound(AMQShortString routingKey, AMQQueue queue)
- {
- List<AMQQueue> queues = _bindingKey2queues.get(normalize(routingKey));
-
- return (queues != null) && queues.contains(queue);
- }
-
- public boolean isBound(AMQShortString routingKey)
- {
- List<AMQQueue> queues = _bindingKey2queues.get(normalize(routingKey));
-
- return (queues != null) && !queues.isEmpty();
- }
-
- public boolean isBound(AMQQueue queue)
- {
- for (List<AMQQueue> queues : _bindingKey2queues.values())
- {
- if (queues.contains(queue))
- {
- return true;
- }
- }
-
- return false;
- }
-
- public boolean hasBindings()
- {
- return !_bindingKey2queues.isEmpty();
- }
-
- public synchronized void deregisterQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- assert queue != null;
- assert rKey != null;
-
- List<AMQQueue> queues = _bindingKey2queues.get(rKey);
- if (queues == null)
- {
- throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName()
- + " with routing key " + rKey + ". No queue was registered with that _routing key");
-
- }
-
- boolean removedQ = queues.remove(queue);
- if (!removedQ)
- {
- throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName()
- + " with routing key " + rKey);
- }
-
-
- if(rKey.contains(HASH_BYTE) || rKey.contains(STAR_BYTE))
- {
- AMQShortString bindingKey = normalize(rKey);
- List<AMQQueue> queues2 = _wildCardBindingKey2queues.get(bindingKey);
- queues2.remove(queue);
- if(queues2.isEmpty())
- {
- _wildCardBindingKey2queues.remove(bindingKey);
- _bindingKey2Tokenized.remove(bindingKey);
- }
-
- }
- else
- {
- List<AMQQueue> queues2 = _simpleBindingKey2queues.get(rKey);
- queues2.remove(queue);
- if(queues2.isEmpty())
- {
- _simpleBindingKey2queues.remove(rKey);
- }
-
- }
-
-
-
-
- if (queues.isEmpty())
- {
- _bindingKey2queues.remove(rKey);
- }
- }
-
- protected ExchangeMBean createMBean() throws AMQException
- {
- try
- {
- return new DestWildExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the topic exchenge mbean", ex);
- throw new AMQException("Exception occured in creating the topic exchenge mbean", ex);
- }
- }
-
- public Map<AMQShortString, List<AMQQueue>> getBindings()
- {
- return _bindingKey2queues;
- }
-
- private List<AMQQueue> getMatchedQueues(AMQShortString routingKey)
- {
-
- List<AMQQueue> list = null;
-
- if(!_wildCardBindingKey2queues.isEmpty())
- {
-
-
- AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR);
-
- final int routingTokensCount = routingTokens.countTokens();
-
-
- AMQShortString[] routingkeyTokens = new AMQShortString[routingTokensCount];
-
- if(routingTokensCount == 1)
- {
- routingkeyTokens[0] =routingKey;
- }
- else
- {
-
-
- int token = 0;
- while (routingTokens.hasMoreTokens())
- {
-
- AMQShortString next = routingTokens.nextToken();
-
- routingkeyTokens[token++] = next;
- }
- }
- for (AMQShortString bindingKey : _wildCardBindingKey2queues.keySet())
- {
-
- AMQShortString[] bindingKeyTokens = _bindingKey2Tokenized.get(bindingKey);
-
-
- boolean matching = true;
- boolean done = false;
-
- int depthPlusRoutingSkip = 0;
- int depthPlusQueueSkip = 0;
-
- final int bindingKeyTokensCount = bindingKeyTokens.length;
-
- while (matching && !done)
- {
-
- if ((bindingKeyTokensCount == depthPlusQueueSkip) || (routingTokensCount == depthPlusRoutingSkip))
- {
- done = true;
-
- // if it was the routing key that ran out of digits
- if (routingTokensCount == depthPlusRoutingSkip)
- {
- if (bindingKeyTokensCount > depthPlusQueueSkip)
- { // a hash and it is the last entry
- matching =
- bindingKeyTokens[depthPlusQueueSkip].equals(AMQP_HASH_TOKEN)
- && (bindingKeyTokensCount == (depthPlusQueueSkip + 1));
- }
- }
- else if (routingTokensCount > depthPlusRoutingSkip)
- {
- // There is still more routing key to check
- matching = false;
- }
-
- continue;
- }
-
- // if the values on the two topics don't match
- if (!bindingKeyTokens[depthPlusQueueSkip].equals(routingkeyTokens[depthPlusRoutingSkip]))
- {
- if (bindingKeyTokens[depthPlusQueueSkip].equals(AMQP_STAR_TOKEN))
- {
- depthPlusQueueSkip++;
- depthPlusRoutingSkip++;
-
- continue;
- }
- else if (bindingKeyTokens[depthPlusQueueSkip].equals(AMQP_HASH_TOKEN))
- {
- // Is this a # at the end
- if (bindingKeyTokensCount == (depthPlusQueueSkip + 1))
- {
- done = true;
-
- continue;
- }
-
- // otherwise # in the middle
- while (routingTokensCount > depthPlusRoutingSkip)
- {
- if (routingkeyTokens[depthPlusRoutingSkip].equals(bindingKeyTokens[depthPlusQueueSkip + 1]))
- {
- depthPlusQueueSkip += 2;
- depthPlusRoutingSkip++;
-
- break;
- }
-
- depthPlusRoutingSkip++;
- }
-
- continue;
- }
-
- matching = false;
- }
-
- depthPlusQueueSkip++;
- depthPlusRoutingSkip++;
- }
-
- if (matching)
- {
- if(list == null)
- {
- list = new ArrayList<AMQQueue>(_wildCardBindingKey2queues.get(bindingKey));
- }
- else
- {
- list.addAll(_wildCardBindingKey2queues.get(bindingKey));
- }
- }
- }
-
- }
- if(!_simpleBindingKey2queues.isEmpty())
- {
- List<AMQQueue> queues = _simpleBindingKey2queues.get(routingKey);
- if(list == null)
- {
- if(queues == null)
- {
- list = Collections.EMPTY_LIST;
- }
- else
- {
- list = new ArrayList<AMQQueue>(queues);
- }
- }
- else if(queues != null)
- {
- list.addAll(queues);
- }
-
- }
-
- return list;
-
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
index 12347c0278..e39c005750 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java
@@ -38,23 +38,22 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
-public class DestNameExchange extends AbstractExchange
+public class DirectExchange extends AbstractExchange
{
- private static final Logger _logger = Logger.getLogger(DestNameExchange.class);
+ private static final Logger _logger = Logger.getLogger(DirectExchange.class);
/**
* Maps from queue name to queue instances
*/
private final Index _index = new Index();
- public static final ExchangeType<DestNameExchange> TYPE = new ExchangeType<DestNameExchange>()
+ public static final ExchangeType<DirectExchange> TYPE = new ExchangeType<DirectExchange>()
{
public AMQShortString getName()
@@ -62,18 +61,18 @@ public class DestNameExchange extends AbstractExchange
return ExchangeDefaults.DIRECT_EXCHANGE_CLASS;
}
- public Class<DestNameExchange> getExchangeClass()
+ public Class<DirectExchange> getExchangeClass()
{
- return DestNameExchange.class;
+ return DirectExchange.class;
}
- public DestNameExchange newInstance(VirtualHost host,
+ public DirectExchange newInstance(VirtualHost host,
AMQShortString name,
boolean durable,
int ticket,
boolean autoDelete) throws AMQException
{
- DestNameExchange exch = new DestNameExchange();
+ DirectExchange exch = new DirectExchange();
exch.initialise(host,name,durable,ticket,autoDelete);
return exch;
}
@@ -88,10 +87,10 @@ public class DestNameExchange extends AbstractExchange
* MBean class implementing the management interfaces.
*/
@MBeanDescription("Management Bean for Direct Exchange")
- private final class DestNameExchangeMBean extends ExchangeMBean
+ private final class DirectExchangeMBean extends ExchangeMBean
{
@MBeanConstructor("Creates an MBean for AMQ direct exchange")
- public DestNameExchangeMBean() throws JMException
+ public DirectExchangeMBean() throws JMException
{
super();
_exchangeType = "direct";
@@ -132,7 +131,7 @@ public class DestNameExchange extends AbstractExchange
try
{
- queue.bind(new AMQShortString(binding), null, DestNameExchange.this);
+ queue.bind(DirectExchange.this, new AMQShortString(binding), null);
}
catch (AMQException ex)
{
@@ -147,7 +146,7 @@ public class DestNameExchange extends AbstractExchange
{
try
{
- return new DestNameExchangeMBean();
+ return new DirectExchangeMBean();
}
catch (JMException ex)
{
@@ -167,11 +166,19 @@ public class DestNameExchange extends AbstractExchange
assert routingKey != null;
if (!_index.add(routingKey, queue))
{
- _logger.debug("Queue " + queue + " is already registered with routing key " + routingKey);
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Queue (" + queue.getName() + ")" + queue + " is already registered with routing key " + routingKey);
+ }
}
else
{
- _logger.debug("Binding queue " + queue + " with routing key " + routingKey + " to exchange " + this);
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Binding queue(" + queue.getName() + ") " + queue + " with routing key " + routingKey
+ + (args == null ? "" : " and arguments " + args.toString())
+ + " to exchange " + this);
+ }
}
}
@@ -187,35 +194,21 @@ public class DestNameExchange extends AbstractExchange
}
}
- public void route(AMQMessage payload) throws AMQException
+ public void route(IncomingMessage payload) throws AMQException
{
- final MessagePublishInfo info = payload.getMessagePublishInfo();
- final AMQShortString routingKey = info.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : info.getRoutingKey();
- final List<AMQQueue> queues = (routingKey == null) ? null : _index.get(routingKey);
- if (queues == null || queues.isEmpty())
+
+ final AMQShortString routingKey = payload.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : payload.getRoutingKey();
+
+ final ArrayList<AMQQueue> queues = (routingKey == null) ? null : _index.get(routingKey);
+
+ if (_logger.isDebugEnabled())
{
- String msg = "Routing key " + routingKey + " is not known to " + this;
- if (info.isMandatory() || info.isImmediate())
- {
- throw new NoRouteException(msg, payload);
- }
- else
- {
- _logger.error("MESSAGE LOSS: Message should be sent on a Dead Letter Queue");
- _logger.warn(msg);
- }
+ _logger.debug("Publishing message to queue " + queues);
}
- else
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Publishing message to queue " + queues);
- }
- payload.enqueue(queues);
+ payload.enqueue(queues);
- }
}
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index 37cd85a8f8..06209c5458 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -23,7 +23,8 @@ package org.apache.qpid.server.exchange;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.queue.AMQMessage;
+
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -53,7 +54,7 @@ public interface Exchange
void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException;
- void route(AMQMessage message) throws AMQException;
+ void route(IncomingMessage message) throws AMQException;
/**
@@ -92,6 +93,6 @@ public interface Exchange
*/
boolean hasBindings();
- Map<AMQShortString, List<AMQQueue>> getBindings();
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index f1b383eac9..e9fd4d548b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -26,10 +26,9 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -95,7 +94,7 @@ public class FanoutExchange extends AbstractExchange
try
{
- queue.bind(new AMQShortString(binding), null, FanoutExchange.this);
+ queue.bind(FanoutExchange.this, new AMQShortString(binding), null);
}
catch (AMQException ex)
{
@@ -183,32 +182,17 @@ public class FanoutExchange extends AbstractExchange
}
}
- public void route(AMQMessage payload) throws AMQException
+ public void route(IncomingMessage payload) throws AMQException
{
- final MessagePublishInfo publishInfo = payload.getMessagePublishInfo();
- final AMQShortString routingKey = publishInfo.getRoutingKey();
- if ((_queues == null) || _queues.isEmpty())
+
+
+ if (_logger.isDebugEnabled())
{
- String msg = "No queues bound to " + this;
- if (publishInfo.isMandatory() || publishInfo.isImmediate())
- {
- throw new NoRouteException(msg, payload);
- }
- else
- {
- _logger.warn(msg);
- }
+ _logger.debug("Publishing message to queue " + _queues);
}
- else
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Publishing message to queue " + _queues);
- }
- payload.enqueue(new ArrayList(_queues));
+ payload.enqueue(new ArrayList(_queues));
- }
}
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index 68ad88c4cb..1ee1f35de6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -31,7 +31,7 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -50,6 +50,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -240,7 +241,7 @@ public class HeadersExchange extends AbstractExchange
}
}
- public void route(AMQMessage payload) throws AMQException
+ public void route(IncomingMessage payload) throws AMQException
{
FieldTable headers = getHeaders(payload.getContentHeaderBody());
if (_logger.isDebugEnabled())
@@ -248,8 +249,10 @@ public class HeadersExchange extends AbstractExchange
_logger.debug("Exchange " + getName() + ": routing message with headers " + headers);
}
boolean routed = false;
+ ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
for (Registration e : _bindings)
{
+
if (e.binding.matches(headers))
{
if (_logger.isDebugEnabled())
@@ -257,25 +260,12 @@ public class HeadersExchange extends AbstractExchange
_logger.debug("Exchange " + getName() + ": delivering message with headers " +
headers + " to " + e.queue.getName());
}
- payload.enqueue(e.queue);
- routed = true;
- }
- }
- if (!routed)
- {
-
- String msg = "Exchange " + getName() + ": message not routable.";
+ queues.add(e.queue);
- if (payload.getMessagePublishInfo().isMandatory() || payload.getMessagePublishInfo().isImmediate())
- {
- throw new NoRouteException(msg, payload);
- }
- else
- {
- _logger.warn(msg);
+ routed = true;
}
-
}
+ payload.enqueue(queues);
}
public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
index eacdad8a8e..ec83161029 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.exchange;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -32,27 +33,27 @@ import org.apache.qpid.server.queue.AMQQueue;
/**
* An index of queues against routing key. Allows multiple queues to be stored
- * against the same key. Used in the DestNameExchange.
+ * against the same key. Used in the DirectExchange.
*/
class Index
{
- private ConcurrentMap<AMQShortString, List<AMQQueue>> _index
- = new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
+ private ConcurrentMap<AMQShortString, ArrayList<AMQQueue>> _index
+ = new ConcurrentHashMap<AMQShortString, ArrayList<AMQQueue>>();
synchronized boolean add(AMQShortString key, AMQQueue queue)
{
- List<AMQQueue> queues = _index.get(key);
+ ArrayList<AMQQueue> queues = _index.get(key);
if(queues == null)
{
- queues = new CopyOnWriteArrayList<AMQQueue>();
- //next call is atomic, so there is no race to create the list
- List<AMQQueue> active = _index.putIfAbsent(key, queues);
- if(active != null)
- {
- //someone added the new one in faster than we did, so use theirs
- queues = active;
- }
+ queues = new ArrayList<AMQQueue>();
+ }
+ else
+ {
+ queues = new ArrayList<AMQQueue>(queues);
}
+ //next call is atomic, so there is no race to create the list
+ _index.put(key, queues);
+
if(queues.contains(queue))
{
return false;
@@ -65,20 +66,28 @@ class Index
synchronized boolean remove(AMQShortString key, AMQQueue queue)
{
- List<AMQQueue> queues = _index.get(key);
+ ArrayList<AMQQueue> queues = _index.get(key);
if (queues != null)
{
+ queues = new ArrayList<AMQQueue>(queues);
boolean removed = queues.remove(queue);
- if (queues.size() == 0)
+ if(removed)
{
- _index.remove(key);
+ if (queues.size() == 0)
+ {
+ _index.remove(key);
+ }
+ else
+ {
+ _index.put(key, queues);
+ }
}
return removed;
}
return false;
}
- List<AMQQueue> get(AMQShortString key)
+ ArrayList<AMQQueue> get(AMQShortString key)
{
return _index.get(key);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
index 7508e80f7f..db9beb6da7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/MessageRouter.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.exchange;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
/**
* Separated out from the ExchangeRegistry interface to allow components
@@ -36,5 +37,5 @@ public interface MessageRouter
*
* @throws org.apache.qpid.AMQException if something goes wrong delivering data
*/
- void routeContent(AMQMessage message) throws AMQException;
+ void routeContent(IncomingMessage message) throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java
index 1d6ab3842d..d18ad7ab14 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/NoRouteException.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.exchange;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.RequiredDeliveryException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.IncomingMessage;
/**
* NoRouteException is a {@link RequiredDeliveryException} that represents the failure case where a manadatory message
@@ -36,9 +37,9 @@ import org.apache.qpid.server.queue.AMQMessage;
*/
public class NoRouteException extends RequiredDeliveryException
{
- public NoRouteException(String msg, AMQMessage message)
+ public NoRouteException(String msg, AMQMessage amqMessage)
{
- super(msg, message);
+ super(msg, amqMessage);
}
public AMQConstant getReplyCode()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
new file mode 100644
index 0000000000..c18cc337fe
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java
@@ -0,0 +1,650 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.exchange;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.AMQShortStringTokenizer;
+import org.apache.qpid.server.management.MBeanConstructor;
+import org.apache.qpid.server.management.MBeanDescription;
+import org.apache.qpid.server.queue.IncomingMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.exchange.topic.TopicParser;
+import org.apache.qpid.server.exchange.topic.TopicMatcherResult;
+import org.apache.qpid.server.filter.MessageFilter;
+import org.apache.qpid.server.filter.JMSSelectorFilter;
+
+import javax.management.JMException;
+import javax.management.MBeanException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.ref.WeakReference;
+
+public class TopicExchange extends AbstractExchange
+{
+
+ public static final ExchangeType<TopicExchange> TYPE = new ExchangeType<TopicExchange>()
+ {
+
+ public AMQShortString getName()
+ {
+ return ExchangeDefaults.TOPIC_EXCHANGE_CLASS;
+ }
+
+ public Class<TopicExchange> getExchangeClass()
+ {
+ return TopicExchange.class;
+ }
+
+ public TopicExchange newInstance(VirtualHost host,
+ AMQShortString name,
+ boolean durable,
+ int ticket,
+ boolean autoDelete) throws AMQException
+ {
+ TopicExchange exch = new TopicExchange();
+ exch.initialise(host, name, durable, ticket, autoDelete);
+ return exch;
+ }
+
+ public AMQShortString getDefaultExchangeName()
+ {
+ return ExchangeDefaults.TOPIC_EXCHANGE_NAME;
+ }
+ };
+
+
+ private static final Logger _logger = Logger.getLogger(TopicExchange.class);
+
+/*
+ private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _bindingKey2queues =
+ new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
+ private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _simpleBindingKey2queues =
+ new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
+ private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _wildCardBindingKey2queues =
+ new ConcurrentHashMap<AMQShortString, List<AMQQueue>>();
+*/
+ // private ConcurrentHashMap<AMQShortString, AMQQueue> _routingKey2queue = new ConcurrentHashMap<AMQShortString, AMQQueue>();
+ private static final byte TOPIC_SEPARATOR = (byte)'.';
+ private static final AMQShortString TOPIC_SEPARATOR_AS_SHORTSTRING = new AMQShortString(".");
+ private static final AMQShortString AMQP_STAR_TOKEN = new AMQShortString("*");
+ private static final AMQShortString AMQP_HASH_TOKEN = new AMQShortString("#");
+
+ private static final byte HASH_BYTE = (byte)'#';
+ private static final byte STAR_BYTE = (byte)'*';
+
+ private final TopicParser _parser = new TopicParser();
+
+ private final Map<AMQShortString, TopicExchangeResult> _topicExchangeResults =
+ new ConcurrentHashMap<AMQShortString, TopicExchangeResult>();
+
+ private final Map<Binding, FieldTable> _bindings = new HashMap<Binding, FieldTable>();
+
+ private final Map<String, WeakReference<JMSSelectorFilter<RuntimeException>>> _selectorCache = new WeakHashMap<String, WeakReference<JMSSelectorFilter<RuntimeException>>>();
+
+ public static class Binding
+ {
+ private final AMQShortString _bindingKey;
+ private final AMQQueue _queue;
+
+ public Binding(AMQShortString bindingKey, AMQQueue queue)
+ {
+ _bindingKey = bindingKey;
+ _queue = queue;
+ }
+
+ public AMQShortString getBindingKey()
+ {
+ return _bindingKey;
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public int hashCode()
+ {
+ return (_bindingKey == null ? 1 : _bindingKey.hashCode())*31 + _queue.hashCode();
+ }
+
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ {
+ return true;
+ }
+ if(o instanceof Binding)
+ {
+ Binding other = (Binding) o;
+ return (_queue == other._queue)
+ && ((_bindingKey == null) ? other._bindingKey == null : _bindingKey.equals(other._bindingKey));
+ }
+ return false;
+ }
+ }
+
+
+
+ private final class TopicExchangeResult implements TopicMatcherResult
+ {
+ private final Map<AMQQueue, Integer> _unfilteredQueues = new ConcurrentHashMap<AMQQueue, Integer>();
+ private final ConcurrentHashMap<AMQQueue, Map<MessageFilter<RuntimeException>,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter<RuntimeException>, Integer>>();
+
+ public void addUnfilteredQueue(AMQQueue queue)
+ {
+ Integer instances = _unfilteredQueues.get(queue);
+ if(instances == null)
+ {
+ _unfilteredQueues.put(queue, 1);
+ }
+ else
+ {
+ _unfilteredQueues.put(queue, instances + 1);
+ }
+ }
+
+ public void removeUnfilteredQueue(AMQQueue queue)
+ {
+ Integer instances = _unfilteredQueues.get(queue);
+ if(instances == 1)
+ {
+ _unfilteredQueues.remove(queue);
+ }
+ else
+ {
+ _unfilteredQueues.put(queue,instances - 1);
+ }
+
+ }
+
+
+ public void addFilteredQueue(AMQQueue queue, MessageFilter<RuntimeException> filter)
+ {
+ Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
+ if(filters == null)
+ {
+ filters = new ConcurrentHashMap<MessageFilter<RuntimeException>,Integer>();
+ _filteredQueues.put(queue, filters);
+ }
+ Integer instances = filters.get(filter);
+ if(instances == null)
+ {
+ filters.put(filter,1);
+ }
+ else
+ {
+ filters.put(filter, instances + 1);
+ }
+
+ }
+
+ public void removeFilteredQueue(AMQQueue queue, MessageFilter<RuntimeException> filter)
+ {
+ Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
+ if(filters != null)
+ {
+ Integer instances = filters.get(filter);
+ if(instances == 1)
+ {
+ filters.remove(filter);
+ if(filters.isEmpty())
+ {
+ _filteredQueues.remove(queue);
+ }
+ }
+ else if(instances != null)
+ {
+ filters.put(filter, instances - 1);
+ }
+
+ }
+
+ }
+
+ public void replaceQueueFilter(AMQQueue queue,
+ MessageFilter<RuntimeException> oldFilter,
+ MessageFilter<RuntimeException> newFilter)
+ {
+ Map<MessageFilter<RuntimeException>,Integer> filters = _filteredQueues.get(queue);
+ Map<MessageFilter<RuntimeException>,Integer> newFilters = new ConcurrentHashMap<MessageFilter<RuntimeException>,Integer>(filters);
+ Integer oldFilterInstances = filters.get(oldFilter);
+ if(oldFilterInstances == 1)
+ {
+ newFilters.remove(oldFilter);
+ }
+ else
+ {
+ newFilters.put(oldFilter, oldFilterInstances-1);
+ }
+ Integer newFilterInstances = filters.get(newFilter);
+ if(newFilterInstances == null)
+ {
+ newFilters.put(newFilter, 1);
+ }
+ else
+ {
+ newFilters.put(newFilter, newFilterInstances+1);
+ }
+ _filteredQueues.put(queue,newFilters);
+ }
+
+ public Collection<AMQQueue> processMessage(IncomingMessage msg, Collection<AMQQueue> queues)
+ {
+ if(queues == null)
+ {
+ if(_filteredQueues.isEmpty())
+ {
+ return new ArrayList<AMQQueue>(_unfilteredQueues.keySet());
+ }
+ else
+ {
+ queues = new HashSet<AMQQueue>();
+ }
+ }
+ else if(!(queues instanceof Set))
+ {
+ queues = new HashSet<AMQQueue>(queues);
+ }
+
+ queues.addAll(_unfilteredQueues.keySet());
+ if(!_filteredQueues.isEmpty())
+ {
+ for(Map.Entry<AMQQueue, Map<MessageFilter<RuntimeException>, Integer>> entry : _filteredQueues.entrySet())
+ {
+ if(!queues.contains(entry.getKey()))
+ {
+ for(MessageFilter<RuntimeException> filter : entry.getValue().keySet())
+ {
+ if(filter.matches(msg))
+ {
+ queues.add(entry.getKey());
+ }
+ }
+ }
+ }
+ }
+ return queues;
+ }
+
+ }
+
+
+ /** TopicExchangeMBean class implements the management interface for the Topic exchanges. */
+ @MBeanDescription("Management Bean for Topic Exchange")
+ private final class TopicExchangeMBean extends ExchangeMBean
+ {
+ @MBeanConstructor("Creates an MBean for AMQ topic exchange")
+ public TopicExchangeMBean() throws JMException
+ {
+ super();
+ _exchangeType = "topic";
+ init();
+ }
+
+ /** returns exchange bindings in tabular form */
+ public TabularData bindings() throws OpenDataException
+ {
+ _bindingList = new TabularDataSupport(_bindinglistDataType);
+ Map<String, List<String>> bindingData = new HashMap<String, List<String>>();
+ for (Binding binding : _bindings.keySet())
+ {
+ String key = binding.getBindingKey().toString();
+ List<String> queueNames = bindingData.get(key);
+ if(queueNames == null)
+ {
+ queueNames = new ArrayList<String>();
+ bindingData.put(key, queueNames);
+ }
+ queueNames.add(binding.getQueue().getName().toString());
+
+ }
+ for(Map.Entry<String, List<String>> entry : bindingData.entrySet())
+ {
+ Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) };
+ CompositeData bindingCompositeData = new CompositeDataSupport(_bindingDataType, _bindingItemNames, bindingItemValues);
+ _bindingList.put(bindingCompositeData);
+ }
+
+ return _bindingList;
+ }
+
+ public void createNewBinding(String queueName, String binding) throws JMException
+ {
+ AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName));
+ if (queue == null)
+ {
+ throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange.");
+ }
+
+ try
+ {
+ queue.bind(TopicExchange.this, new AMQShortString(binding), null);
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex);
+ }
+ }
+
+ } // End of MBean class
+
+ public AMQShortString getType()
+ {
+ return ExchangeDefaults.TOPIC_EXCHANGE_CLASS;
+ }
+
+ public synchronized void registerQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ assert queue != null;
+ assert rKey != null;
+
+ _logger.debug("Registering queue " + queue.getName() + " with routing key " + rKey);
+
+
+ AMQShortString routingKey;
+
+ if(rKey.contains(HASH_BYTE) || rKey.contains(STAR_BYTE))
+ {
+ routingKey = normalize(rKey);
+ }
+ else
+ {
+ routingKey = rKey;
+ }
+
+ Binding binding = new Binding(rKey, queue);
+
+ if(_bindings.containsKey(binding))
+ {
+ FieldTable oldArgs = _bindings.get(binding);
+ TopicExchangeResult result = _topicExchangeResults.get(routingKey);
+
+ if(argumentsContainSelector(args))
+ {
+ if(argumentsContainSelector(oldArgs))
+ {
+ result.replaceQueueFilter(queue,createSelectorFilter(oldArgs), createSelectorFilter(args));
+ }
+ else
+ {
+ result.addFilteredQueue(queue,createSelectorFilter(args));
+ result.removeUnfilteredQueue(queue);
+ }
+ }
+ else
+ {
+ if(argumentsContainSelector(oldArgs))
+ {
+ result.addUnfilteredQueue(queue);
+ result.removeFilteredQueue(queue, createSelectorFilter(oldArgs));
+ }
+ else
+ {
+ // TODO - fix control flow
+ return;
+ }
+ }
+
+ }
+ else
+ {
+
+ TopicExchangeResult result = _topicExchangeResults.get(routingKey);
+ if(result == null)
+ {
+ result = new TopicExchangeResult();
+ if(argumentsContainSelector(args))
+ {
+ result.addFilteredQueue(queue, createSelectorFilter(args));
+ }
+ else
+ {
+ result.addUnfilteredQueue(queue);
+ }
+ _parser.addBinding(routingKey, result);
+ _topicExchangeResults.put(routingKey,result);
+ }
+ else
+ {
+ if(argumentsContainSelector(args))
+ {
+ result.addFilteredQueue(queue, createSelectorFilter(args));
+ }
+ else
+ {
+ result.addUnfilteredQueue(queue);
+ }
+ }
+ _bindings.put(binding, args);
+ }
+
+
+ }
+
+ private JMSSelectorFilter<RuntimeException> createSelectorFilter(final FieldTable args)
+ throws AMQException
+ {
+
+ final String selectorString = args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue());
+ WeakReference<JMSSelectorFilter<RuntimeException>> selectorRef = _selectorCache.get(selectorString);
+ JMSSelectorFilter selector = null;
+
+ if(selectorRef == null || (selector = selectorRef.get())==null)
+ {
+ selector = new JMSSelectorFilter<RuntimeException>(selectorString);
+ _selectorCache.put(selectorString, new WeakReference<JMSSelectorFilter<RuntimeException>>(selector));
+ }
+ return selector;
+ }
+
+ private static boolean argumentsContainSelector(final FieldTable args)
+ {
+ return args != null && args.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()) && args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()).trim().length() != 0;
+ }
+
+ private AMQShortString normalize(AMQShortString routingKey)
+ {
+ if(routingKey == null)
+ {
+ routingKey = AMQShortString.EMPTY_STRING;
+ }
+
+ AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR);
+
+ List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>();
+
+ while (routingTokens.hasMoreTokens())
+ {
+ subscriptionList.add(routingTokens.nextToken());
+ }
+
+ int size = subscriptionList.size();
+
+ for (int index = 0; index < size; index++)
+ {
+ // if there are more levels
+ if ((index + 1) < size)
+ {
+ if (subscriptionList.get(index).equals(AMQP_HASH_TOKEN))
+ {
+ if (subscriptionList.get(index + 1).equals(AMQP_HASH_TOKEN))
+ {
+ // we don't need #.# delete this one
+ subscriptionList.remove(index);
+ size--;
+ // redo this normalisation
+ index--;
+ }
+
+ if (subscriptionList.get(index + 1).equals(AMQP_STAR_TOKEN))
+ {
+ // we don't want #.* swap to *.#
+ // remove it and put it in at index + 1
+ subscriptionList.add(index + 1, subscriptionList.remove(index));
+ }
+ }
+ } // if we have more levels
+ }
+
+
+
+ AMQShortString normalizedString = AMQShortString.join(subscriptionList, TOPIC_SEPARATOR_AS_SHORTSTRING);
+
+ return normalizedString;
+ }
+
+ public void route(IncomingMessage payload) throws AMQException
+ {
+
+ final AMQShortString routingKey = payload.getRoutingKey();
+
+ // The copy here is unfortunate, but not too bad relevant to the amount of
+ // things created and copied in getMatchedQueues
+ ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>();
+ queues.addAll(getMatchedQueues(payload, routingKey));
+
+ if(queues == null || queues.isEmpty())
+ {
+ _logger.info("Message routing key: " + payload.getRoutingKey() + " No routes.");
+ }
+
+ payload.enqueue(queues);
+
+ }
+
+ public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
+ {
+ return isBound(routingKey, queue);
+ }
+
+ public boolean isBound(AMQShortString routingKey, AMQQueue queue)
+ {
+ Binding binding = new Binding(routingKey, queue);
+
+ return _bindings.containsKey(binding);
+ }
+
+ public boolean isBound(AMQShortString routingKey)
+ {
+ for(Binding b : _bindings.keySet())
+ {
+ if(b.getBindingKey().equals(routingKey))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isBound(AMQQueue queue)
+ {
+ for(Binding b : _bindings.keySet())
+ {
+ if(b.getQueue().equals(queue))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean hasBindings()
+ {
+ return !_bindings.isEmpty();
+ }
+
+ public synchronized void deregisterQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ assert queue != null;
+ assert rKey != null;
+
+ Binding binding = new Binding(rKey, queue);
+
+
+ if (!_bindings.containsKey(binding))
+ {
+ throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue.getName() + " was not registered with exchange " + this.getName()
+ + " with routing key " + rKey + ".");
+ }
+
+ FieldTable bindingArgs = _bindings.remove(binding);
+ AMQShortString bindingKey = normalize(rKey);
+ TopicExchangeResult result = _topicExchangeResults.get(bindingKey);
+ if(argumentsContainSelector(bindingArgs))
+ {
+ result.removeFilteredQueue(queue, createSelectorFilter(bindingArgs));
+ }
+ else
+ {
+ result.removeUnfilteredQueue(queue);
+ }
+
+ }
+
+ protected ExchangeMBean createMBean() throws AMQException
+ {
+ try
+ {
+ return new TopicExchangeMBean();
+ }
+ catch (JMException ex)
+ {
+ _logger.error("Exception occured in creating the topic exchenge mbean", ex);
+ throw new AMQException("Exception occured in creating the topic exchenge mbean", ex);
+ }
+ }
+
+ private Collection<AMQQueue> getMatchedQueues(IncomingMessage message, AMQShortString routingKey)
+ {
+
+ Collection<TopicMatcherResult> results = _parser.parse(routingKey);
+ if(results.isEmpty())
+ {
+ return Collections.EMPTY_SET;
+ }
+ else
+ {
+ Collection<AMQQueue> queues = results.size() == 1 ? null : new HashSet<AMQQueue>();
+ for(TopicMatcherResult result : results)
+ {
+
+ queues = ((TopicExchangeResult)result).processMessage(message, queues);
+ }
+ return queues;
+ }
+
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKey.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKey.java
new file mode 100644
index 0000000000..8fdb91cbef
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKey.java
@@ -0,0 +1,40 @@
+package org.apache.qpid.server.exchange.headers;
+
+import org.apache.qpid.framing.AMQShortString;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class HeaderKey
+{
+ public static final HeaderKey UNKNOWN = new HeaderKey(new AMQShortString("<< UNKNOWN >>"));
+ private AMQShortString _key;
+
+ public HeaderKey(final AMQShortString key)
+ {
+ _key = key;
+ }
+
+ public String toString()
+ {
+ return _key.toString();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKeyDictionary.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKeyDictionary.java
new file mode 100644
index 0000000000..7be99a88c9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderKeyDictionary.java
@@ -0,0 +1,50 @@
+package org.apache.qpid.server.exchange.headers;
+
+import org.apache.qpid.framing.AMQShortString;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class HeaderKeyDictionary
+{
+
+ private final Map<AMQShortString, HeaderKey> _dictionary = new HashMap<AMQShortString, HeaderKey>();
+
+
+ public HeaderKey get(final AMQShortString key)
+ {
+ HeaderKey headerKey = _dictionary.get(key);
+ return headerKey == null ? HeaderKey.UNKNOWN : headerKey;
+ }
+
+ public HeaderKey getOrCreate(final AMQShortString key)
+ {
+ HeaderKey headerKey = _dictionary.get(key);
+ if(headerKey == null)
+ {
+ headerKey = new HeaderKey(key);
+ _dictionary.put(key, headerKey);
+ }
+ return headerKey;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderMatcherResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderMatcherResult.java
new file mode 100644
index 0000000000..518064bb29
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeaderMatcherResult.java
@@ -0,0 +1,25 @@
+package org.apache.qpid.server.exchange.headers;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class HeaderMatcherResult
+{
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersMatcherDFAState.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersMatcherDFAState.java
new file mode 100644
index 0000000000..9da93d483a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersMatcherDFAState.java
@@ -0,0 +1,339 @@
+package org.apache.qpid.server.exchange.headers;
+
+import org.apache.qpid.framing.AMQTypedValue;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.exchange.topic.TopicMatcherDFAState;
+import org.apache.qpid.server.exchange.topic.TopicWord;
+import org.apache.qpid.server.exchange.topic.TopicMatcherResult;
+
+import java.util.*;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class HeadersMatcherDFAState
+{
+
+
+ private final Collection<HeaderMatcherResult> _results;
+ private final Map<HeaderKey, Map<AMQTypedValue,HeadersMatcherDFAState>> _nextStateMap;
+ private final HeaderKeyDictionary _dictionary;
+
+ public HeadersMatcherDFAState(Map<HeaderKey, Map<AMQTypedValue,HeadersMatcherDFAState>> nextStateMap,
+ Collection<HeaderMatcherResult> results,
+ HeaderKeyDictionary dictionary)
+ {
+ _nextStateMap = nextStateMap;
+ _results = results;
+ _dictionary = dictionary;
+ }
+
+
+ public Collection<HeaderMatcherResult> match(final FieldTable table)
+ {
+ return match(table.iterator());
+ }
+
+
+
+ public Collection<HeaderMatcherResult> match(Iterator<Map.Entry<AMQShortString,AMQTypedValue>> fieldTableIterator)
+ {
+
+ if(_nextStateMap.isEmpty())
+ {
+ return _results;
+ }
+
+ while(fieldTableIterator.hasNext())
+ {
+
+ Map.Entry<AMQShortString, AMQTypedValue> fieldTableEntry = fieldTableIterator.next();
+ HeaderKey key = _dictionary.get(fieldTableEntry.getKey());
+ if(key != HeaderKey.UNKNOWN)
+ {
+ Map<AMQTypedValue, HeadersMatcherDFAState> valueToStateMap = _nextStateMap.get(key);
+
+ if(valueToStateMap != null)
+ {
+ HeadersMatcherDFAState nextState = valueToStateMap.get(fieldTableEntry.getValue());
+
+ if(nextState == null)
+ {
+ nextState = valueToStateMap.get(null);
+ }
+ if(nextState != null && nextState != this)
+ {
+ return nextState.match(fieldTableIterator);
+ }
+ }
+
+ }
+ }
+
+ return _results;
+
+ }
+
+
+ HeadersMatcherDFAState mergeStateMachines(HeadersMatcherDFAState otherStateMachine)
+ {
+
+ assert(otherStateMachine._dictionary == _dictionary);
+
+ Map<Set<HeadersMatcherDFAState>, HeadersMatcherDFAState> newStateMap= new HashMap<Set<HeadersMatcherDFAState>, HeadersMatcherDFAState>();
+
+ Collection<HeaderMatcherResult> results;
+
+ if(_results.isEmpty())
+ {
+ results = otherStateMachine._results;
+ }
+ else if(otherStateMachine._results.isEmpty())
+ {
+ results = _results;
+ }
+ else
+ {
+ results = new HashSet<HeaderMatcherResult>(_results);
+ results.addAll(otherStateMachine._results);
+ }
+
+
+ final Map<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> newNextStateMap = new HashMap<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>>();
+
+ HeadersMatcherDFAState newState = new HeadersMatcherDFAState(newNextStateMap, results, _dictionary);
+
+
+ Set<HeadersMatcherDFAState> oldStates = new HashSet<HeadersMatcherDFAState>();
+ oldStates.add(this);
+ oldStates.add(otherStateMachine);
+
+ newStateMap.put(oldStates, newState);
+
+ mergeStateMachines(oldStates, newNextStateMap, newStateMap);
+
+ return newState;
+
+
+ }
+
+ private void mergeStateMachines(final Set<HeadersMatcherDFAState> oldStates,
+ final Map<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> newNextStateMap,
+ final Map<Set<HeadersMatcherDFAState>, HeadersMatcherDFAState> newStateMap)
+ {
+ Map<HeaderKey, Map<AMQTypedValue, Set<HeadersMatcherDFAState>>> nfaMap = new HashMap<HeaderKey, Map<AMQTypedValue, Set<HeadersMatcherDFAState>>>();
+
+ Set<HeaderKey> distinctKeys = new HashSet<HeaderKey>();
+
+ for(HeadersMatcherDFAState state : oldStates)
+ {
+ Map<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> map = state._nextStateMap;
+
+ for(Map.Entry<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> entry : map.entrySet())
+ {
+ Map<AMQTypedValue, Set<HeadersMatcherDFAState>> valueToStatesMap = nfaMap.get(entry.getKey());
+
+ if(valueToStatesMap == null)
+ {
+ valueToStatesMap = new HashMap<AMQTypedValue, Set<HeadersMatcherDFAState>>();
+ nfaMap.put(entry.getKey(), valueToStatesMap);
+ }
+
+ for(Map.Entry<AMQTypedValue, HeadersMatcherDFAState> valueToStateEntry : entry.getValue().entrySet())
+ {
+ Set<HeadersMatcherDFAState> states = valueToStatesMap.get(valueToStateEntry.getKey());
+ if(states == null)
+ {
+ states = new HashSet<HeadersMatcherDFAState>();
+ valueToStatesMap.put(valueToStateEntry.getKey(),states);
+ }
+ states.add(valueToStateEntry.getValue());
+ }
+
+ distinctKeys.add(entry.getKey());
+ }
+ }
+
+ Map<HeaderKey, Set<HeadersMatcherDFAState>> anyValueStates = new HashMap<HeaderKey, Set<HeadersMatcherDFAState>>();
+
+ for(HeaderKey distinctKey : distinctKeys)
+ {
+ Map<AMQTypedValue, Set<HeadersMatcherDFAState>> valueToStateMap = nfaMap.get(distinctKey);
+ if(valueToStateMap != null)
+ {
+ Set<HeadersMatcherDFAState> statesForKeyDefault = valueToStateMap.get(null);
+ if(statesForKeyDefault != null)
+ {
+ anyValueStates.put(distinctKey, statesForKeyDefault);
+ }
+ }
+ }
+
+ // add the defaults for "null" to all other specified values of a given header key
+
+ for( Map.Entry<HeaderKey,Map<AMQTypedValue,Set<HeadersMatcherDFAState>>> entry : nfaMap.entrySet())
+ {
+ Map<AMQTypedValue, Set<HeadersMatcherDFAState>> valueToStatesMap = entry.getValue();
+ for(Map.Entry<AMQTypedValue, Set<HeadersMatcherDFAState>> valueToStates : valueToStatesMap.entrySet())
+ {
+ if(valueToStates.getKey() != null)
+ {
+
+
+ Set<HeadersMatcherDFAState> defaults = anyValueStates.get(entry.getKey());
+ if(defaults != null)
+ {
+ valueToStates.getValue().addAll(defaults);
+ }
+ }
+ }
+ }
+
+ // if a given header key is not mentioned in the map of a machine; then that machine would stay at the same state
+ // for that key.
+ for(HeaderKey distinctKey : distinctKeys)
+ {
+ Map<AMQTypedValue, Set<HeadersMatcherDFAState>> valueToStatesMap = nfaMap.get(distinctKey);
+ for(HeadersMatcherDFAState oldState : oldStates)
+ {
+ if(!oldState._nextStateMap.containsKey(distinctKey))
+ {
+ for(Set<HeadersMatcherDFAState> endStates : valueToStatesMap.values())
+ {
+ endStates.add(oldState);
+ }
+ }
+ }
+ }
+
+
+
+
+ for(Map.Entry<HeaderKey,Map<AMQTypedValue,Set<HeadersMatcherDFAState>>> transitionClass : nfaMap.entrySet())
+ {
+ Map<AMQTypedValue, HeadersMatcherDFAState> valueToDFAState = newNextStateMap.get(transitionClass.getKey());
+ if(valueToDFAState == null)
+ {
+ valueToDFAState = new HashMap<AMQTypedValue, HeadersMatcherDFAState>();
+ newNextStateMap.put(transitionClass.getKey(), valueToDFAState);
+ }
+
+ for(Map.Entry<AMQTypedValue,Set<HeadersMatcherDFAState>> transition : transitionClass.getValue().entrySet())
+ {
+ Set<HeadersMatcherDFAState> destinations = transition.getValue();
+
+
+ HeadersMatcherDFAState nextState = newStateMap.get(destinations);
+
+ if(nextState == null)
+ {
+
+ if(destinations.size() == 1)
+ {
+ nextState = destinations.iterator().next();
+ newStateMap.put(destinations, nextState);
+ }
+ else
+ {
+ Collection<HeaderMatcherResult> results;
+
+ Set<Collection<HeaderMatcherResult>> resultSets = new HashSet<Collection<HeaderMatcherResult>>();
+ for(HeadersMatcherDFAState destination : destinations)
+ {
+ resultSets.add(destination._results);
+ }
+ resultSets.remove(Collections.EMPTY_SET);
+ if(resultSets.size() == 0)
+ {
+ results = Collections.EMPTY_SET;
+ }
+ else if(resultSets.size() == 1)
+ {
+ results = resultSets.iterator().next();
+ }
+ else
+ {
+ results = new HashSet<HeaderMatcherResult>();
+ for(Collection<HeaderMatcherResult> oldResult : resultSets)
+ {
+ results.addAll(oldResult);
+ }
+ }
+
+ final Map<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> nextStateMap = new HashMap<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>>();
+
+ nextState = new HeadersMatcherDFAState(nextStateMap, results, _dictionary);
+ newStateMap.put(destinations, nextState);
+
+ mergeStateMachines(
+ destinations,
+ nextStateMap,
+ newStateMap);
+
+
+ }
+
+
+ }
+ valueToDFAState.put(transition.getKey(),nextState);
+ }
+ }
+
+
+
+ final ArrayList<HeaderKey> removeKeyList = new ArrayList<HeaderKey>();
+
+ for(Map.Entry<HeaderKey,Map<AMQTypedValue,HeadersMatcherDFAState>> entry : _nextStateMap.entrySet())
+ {
+ final ArrayList<AMQTypedValue> removeValueList = new ArrayList<AMQTypedValue>();
+
+ for(Map.Entry<AMQTypedValue,HeadersMatcherDFAState> valueToDFAState : entry.getValue().entrySet())
+ {
+ if(valueToDFAState.getValue() == this)
+ {
+ HeadersMatcherDFAState defaultState = entry.getValue().get(null);
+ if(defaultState == null || defaultState == this)
+ {
+ removeValueList.add(valueToDFAState.getKey());
+ }
+ }
+ }
+
+ for(AMQTypedValue removeValue : removeValueList)
+ {
+ entry.getValue().remove(removeValue);
+ }
+
+ if(entry.getValue().isEmpty())
+ {
+ removeKeyList.add(entry.getKey());
+ }
+
+ }
+
+ for(HeaderKey removeKey : removeKeyList)
+ {
+ _nextStateMap.remove(removeKey);
+ }
+
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
new file mode 100644
index 0000000000..85e74122c3
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
@@ -0,0 +1,439 @@
+package org.apache.qpid.server.exchange.headers;
+
+import org.apache.qpid.framing.*;
+
+import java.util.*;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class HeadersParser
+{
+
+ private final HeaderKeyDictionary _dictionary = new HeaderKeyDictionary();
+ private static final AMQShortString MATCHING_TYPE_KEY = new AMQShortString("x-match");
+ private static final String ANY_MATCHING = "any";
+ private static final AMQShortString RESERVED_KEY_PREFIX = new AMQShortString("x-");
+
+
+ HeadersMatcherDFAState createStateMachine(FieldTable bindingArguments, HeaderMatcherResult result)
+ {
+ String matchingType = bindingArguments.getString(MATCHING_TYPE_KEY);
+ boolean matchAny = matchingType.equalsIgnoreCase(ANY_MATCHING);
+ if(matchAny)
+ {
+ return createStateMachineForAnyMatch(bindingArguments, result);
+ }
+ else
+ {
+ return createStateMachineForAllMatch(bindingArguments, result);
+ }
+
+
+ }
+
+
+ private HeadersMatcherDFAState createStateMachineForAnyMatch(final FieldTable bindingArguments,
+ final HeaderMatcherResult result)
+ {
+
+ // DFAs for "any" matches have only two states, "not-matched" and "matched"... they start in the former
+ // and upon meeting any of the criteria they move to the latter
+
+ //noinspection unchecked
+ final HeadersMatcherDFAState successState =
+ new HeadersMatcherDFAState(Collections.EMPTY_MAP,Collections.singleton(result),_dictionary);
+
+ Map<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>> nextStateMap =
+ new HashMap<HeaderKey, Map<AMQTypedValue, HeadersMatcherDFAState>>();
+
+ Set<AMQShortString> seenKeys = new HashSet<AMQShortString>();
+
+ Iterator<Map.Entry<AMQShortString, AMQTypedValue>> tableIterator = bindingArguments.iterator();
+
+ while(tableIterator.hasNext())
+ {
+ final Map.Entry<AMQShortString, AMQTypedValue> entry = tableIterator.next();
+ final AMQShortString key = entry.getKey();
+ final AMQTypedValue value = entry.getValue();
+
+
+ if(seenKeys.add(key) && !key.startsWith(RESERVED_KEY_PREFIX))
+ {
+ final AMQType type = value.getType();
+
+ final HeaderKey headerKey = _dictionary.getOrCreate(key);
+ final Map<AMQTypedValue, HeadersMatcherDFAState> valueMap;
+
+ if(type == AMQType.VOID ||
+ ((type == AMQType.ASCII_STRING || type == AMQType.WIDE_STRING) && ((CharSequence)value.getValue()).length() == 0))
+ {
+ valueMap = Collections.singletonMap(null,successState);
+
+ }
+ else
+ {
+ valueMap = Collections.singletonMap(value,successState);
+ }
+ nextStateMap.put(headerKey,valueMap);
+
+ }
+
+ }
+
+ if(seenKeys.size() == 0)
+ {
+ return successState;
+ }
+ else
+ {
+ return new HeadersMatcherDFAState(nextStateMap,Collections.EMPTY_SET,_dictionary);
+ }
+
+
+ }
+
+
+ private HeadersMatcherDFAState createStateMachineForAllMatch(final FieldTable bindingArguments,
+ final HeaderMatcherResult result)
+ {
+ // DFAs for "all" matches have a "success" state, a "fail" state, and states for every subset of
+ // matches which are possible, starting with the empty subset. For example if we have a binding
+ // { x-match="all"
+ // a=1
+ // b=1
+ // c=1
+ // d=1 }
+ // Then we would have the following states
+ // (1) Seen none of a, b, c, or d
+ // (2) Seen a=1 ; none of b,c, or d
+ // (3) Seen b=1 ; none of a,c, or d
+ // (4) Seen c=1 ; none of a,b, or d
+ // (5) Seen d=1 ; none of a,b, or c
+ // (6) Seen a=1,b=1 ; none of c,d
+ // (7) Seen a=1,c=1 ; none of b,d
+ // (8) Seen a=1,d=1 ; none of b,c
+ // (9) Seen b=1,c=1 ; none of a,d
+ //(10) Seen b=1,d=1 ; none of c,d
+ //(11) Seen c=1,d=1 ; none of a,b
+ //(12) Seen a=1,b=1,c=1 ; not d
+ //(13) Seen a=1,b=1,d=1 ; not c
+ //(14) Seen a=1,c=1,d=1 ; not b
+ //(15) Seen b=1,c=1,d=1 ; not a
+ //(16) success
+ //(17) fail
+ //
+ // All states but (16) can transition to (17); additionally:
+ // (1) can transition to (2),(3),(4),(5)
+ // (2) can transition to (6),(7),(8)
+ // (3) can transition to (6),(9),(10)
+ // (4) can transition to (7),(9),(11)
+ // (5) can transition to (8),(10),(11)
+ // (6) can transition to (12),(13)
+ // (7) can transition to (12),(14)
+ // (8) can transition to (13),(14)
+ // (9) can transition to (12),(15)
+ //(10) can transition to (13),(15)
+ //(11) can transition to (14),(15)
+ //(12)-(15) can transition to (16)
+
+ Set<AMQShortString> seenKeys = new HashSet<AMQShortString>();
+ List<KeyValuePair> requiredTerms = new ArrayList<KeyValuePair>(bindingArguments.size());
+
+ Iterator<Map.Entry<AMQShortString, AMQTypedValue>> tableIterator = bindingArguments.iterator();
+
+
+
+ while(tableIterator.hasNext())
+ {
+ final Map.Entry<AMQShortString, AMQTypedValue> entry = tableIterator.next();
+ final AMQShortString key = entry.getKey();
+ final AMQTypedValue value = entry.getValue();
+
+
+ if(seenKeys.add(key) && !key.startsWith(RESERVED_KEY_PREFIX))
+ {
+ final AMQType type = value.getType();
+
+ if(type == AMQType.VOID ||
+ ((type == AMQType.ASCII_STRING || type == AMQType.WIDE_STRING) && ((CharSequence)value.getValue()).length() == 0))
+ {
+ requiredTerms.add(new KeyValuePair(_dictionary.getOrCreate(key),null));
+ }
+ else
+ {
+ requiredTerms.add(new KeyValuePair(_dictionary.getOrCreate(key),value));
+ }
+ }
+
+ }
+
+ final HeadersMatcherDFAState successState =
+ new HeadersMatcherDFAState(Collections.EMPTY_MAP,Collections.singleton(result),_dictionary);
+
+ final HeadersMatcherDFAState failState =
+ new HeadersMatcherDFAState(Collections.EMPTY_MAP,Collections.EMPTY_SET,_dictionary);
+
+ Map<Set<KeyValuePair>, HeadersMatcherDFAState> notSeenTermsToStateMap =
+ new HashMap<Set<KeyValuePair>, HeadersMatcherDFAState>();
+
+ notSeenTermsToStateMap.put(Collections.EMPTY_SET, successState);
+
+
+ final int numberOfTerms = requiredTerms.size();
+
+ for(int numMissingTerms = 1; numMissingTerms <= numberOfTerms; numMissingTerms++)
+ {
+ int[] pos = new int[numMissingTerms];
+ for(int i = 0; i < numMissingTerms; i++)
+ {
+ pos[i] = i;
+ }
+
+ final int maxTermValue = (numberOfTerms - (numMissingTerms - 1));
+
+ while(pos[0] < maxTermValue)
+ {
+
+ Set<KeyValuePair> stateSet = new HashSet<KeyValuePair>();
+ for(int posIndex = 0; posIndex < pos.length; posIndex++)
+ {
+ stateSet.add(requiredTerms.get(pos[posIndex]));
+ }
+
+ final Map<HeaderKey, Map<AMQTypedValue,HeadersMatcherDFAState>> nextStateMap =
+ new HashMap<HeaderKey, Map<AMQTypedValue,HeadersMatcherDFAState>>();
+
+
+ for(int posIndex = 0; posIndex < pos.length; posIndex++)
+ {
+ KeyValuePair nextTerm = requiredTerms.get(pos[posIndex]);
+ HashSet<KeyValuePair> nextStateSet =
+ new HashSet<KeyValuePair>(stateSet);
+ nextStateSet.remove(nextTerm);
+
+ Map<AMQTypedValue, HeadersMatcherDFAState> valueToStateMap =
+ new HashMap<AMQTypedValue, HeadersMatcherDFAState>();
+ nextStateMap.put(nextTerm._key, valueToStateMap);
+
+ valueToStateMap.put( nextTerm._value,notSeenTermsToStateMap.get(nextStateSet));
+ if(nextTerm._value != null)
+ {
+ valueToStateMap.put(null, failState);
+ }
+
+
+ }
+
+
+ HeadersMatcherDFAState newState = new HeadersMatcherDFAState(nextStateMap, Collections.EMPTY_SET, _dictionary);
+
+ notSeenTermsToStateMap.put(stateSet, newState);
+
+ int i = numMissingTerms;
+ while(i-- != 0)
+ {
+ if(++pos[i] <= numberOfTerms -(numMissingTerms-i))
+ {
+ int k = pos[i];
+ for(int j = i+1; j < numMissingTerms; j++)
+ {
+ pos[j] = ++k;
+ }
+ break;
+ }
+ }
+ }
+
+
+
+
+ }
+
+
+ return notSeenTermsToStateMap.get(new HashSet<KeyValuePair>(requiredTerms));
+
+
+
+ }
+
+ public static void main(String[] args) throws AMQFrameDecodingException
+ {
+
+ FieldTable bindingTable = new FieldTable();
+
+ bindingTable.setString(new AMQShortString("x-match"),"all");
+ bindingTable.setInteger("a",1);
+ bindingTable.setVoid(new AMQShortString("b"));
+ bindingTable.setString("c","");
+ bindingTable.setInteger("d",4);
+ bindingTable.setInteger("e",1);
+
+
+
+ FieldTable bindingTable2 = new FieldTable();
+ bindingTable2.setString(new AMQShortString("x-match"),"all");
+ bindingTable2.setInteger("a",1);
+ bindingTable2.setVoid(new AMQShortString("b"));
+ bindingTable2.setString("c","");
+ bindingTable2.setInteger("d",4);
+ bindingTable2.setInteger("e",1);
+ bindingTable2.setInteger("f",1);
+
+
+ FieldTable table = new FieldTable();
+ table.setInteger("a",1);
+ table.setInteger("b",2);
+ table.setString("c","");
+ table.setInteger("d",4);
+ table.setInteger("e",1);
+ table.setInteger("f",1);
+ table.setInteger("h",1);
+ table.setInteger("i",1);
+ table.setInteger("j",1);
+ table.setInteger("k",1);
+ table.setInteger("l",1);
+
+ org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.allocate( (int) table.getEncodedSize());
+ EncodingUtils.writeFieldTableBytes(buffer, table);
+ buffer.flip();
+
+ FieldTable table2 = EncodingUtils.readFieldTable(buffer);
+
+
+
+ FieldTable bindingTable3 = new FieldTable();
+ bindingTable3.setString(new AMQShortString("x-match"),"any");
+ bindingTable3.setInteger("a",1);
+ bindingTable3.setInteger("b",3);
+
+
+ FieldTable bindingTable4 = new FieldTable();
+ bindingTable4.setString(new AMQShortString("x-match"),"any");
+ bindingTable4.setVoid(new AMQShortString("a"));
+
+
+ FieldTable bindingTable5 = new FieldTable();
+ bindingTable5.setString(new AMQShortString("x-match"),"all");
+ bindingTable5.setString(new AMQShortString("h"),"hello");
+
+ for(int i = 0; i < 100; i++)
+ {
+ printMatches(new FieldTable[] {bindingTable5} , table2);
+ }
+
+
+
+ }
+
+
+
+ private static void printMatches(final FieldTable[] bindingKeys, final FieldTable routingKey)
+ {
+ HeadersMatcherDFAState sm = null;
+ Map<HeaderMatcherResult, String> resultMap = new HashMap<HeaderMatcherResult, String>();
+
+ HeadersParser parser = new HeadersParser();
+
+ for(int i = 0; i < bindingKeys.length; i++)
+ {
+ HeaderMatcherResult r = new HeaderMatcherResult();
+ resultMap.put(r, bindingKeys[i].toString());
+
+
+ if(i==0)
+ {
+ sm = parser.createStateMachine(bindingKeys[i], r);
+ }
+ else
+ {
+ sm = sm.mergeStateMachines(parser.createStateMachine(bindingKeys[i], r));
+ }
+ }
+
+ Collection<HeaderMatcherResult> results = null;
+ long beforeTime = System.currentTimeMillis();
+ for(int i = 0; i < 1000000; i++)
+ {
+ routingKey.size();
+
+ assert sm != null;
+ results = sm.match(routingKey);
+
+ }
+ long elapsed = System.currentTimeMillis() - beforeTime;
+ System.out.println("1000000 Iterations took: " + elapsed);
+ Collection<String> resultStrings = new ArrayList<String>();
+
+ assert results != null;
+ for(HeaderMatcherResult result : results)
+ {
+ resultStrings.add(resultMap.get(result));
+ }
+
+ final ArrayList<String> nonMatches = new ArrayList<String>();
+ for(FieldTable key : bindingKeys)
+ {
+ nonMatches.add(key.toString());
+ }
+ nonMatches.removeAll(resultStrings);
+ System.out.println("\""+routingKey+"\" matched with " + resultStrings + " DID NOT MATCH with " + nonMatches);
+
+
+ }
+
+
+ public final static class KeyValuePair
+ {
+ public final HeaderKey _key;
+ public final AMQTypedValue _value;
+ private final int _hashCode;
+
+ public KeyValuePair(final HeaderKey key, final AMQTypedValue value)
+ {
+ _key = key;
+ _value = value;
+ int hash = (1 + 31 * _key.hashCode());
+ if(_value != null)
+ {
+ hash+=_value.hashCode();
+ }
+ _hashCode = hash;
+ }
+
+ public int hashCode()
+ {
+ return _hashCode;
+ }
+
+ public boolean equals(Object o)
+ {
+ KeyValuePair other = (KeyValuePair)o;
+ return (_key == other._key) && (_value == null ? other._value == null : _value.equals(other._value));
+ }
+
+
+ public String toString()
+ {
+ return "{" + _key + " -> " + _value + "}";
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java
new file mode 100644
index 0000000000..36076cf75b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java
@@ -0,0 +1,295 @@
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.AMQShortStringTokenizer;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class TopicMatcherDFAState
+{
+ private static final AtomicInteger stateId = new AtomicInteger();
+
+ private final int _id = stateId.incrementAndGet();
+
+ private final Collection<TopicMatcherResult> _results;
+ private final Map<TopicWord, TopicMatcherDFAState> _nextStateMap;
+ private static final byte TOPIC_DELIMITTER = (byte)'.';
+
+
+ public TopicMatcherDFAState(Map<TopicWord, TopicMatcherDFAState> nextStateMap,
+ Collection<TopicMatcherResult> results )
+ {
+ _nextStateMap = nextStateMap;
+ _results = results;
+ }
+
+
+ public TopicMatcherDFAState nextState(TopicWord word)
+ {
+ final TopicMatcherDFAState nextState = _nextStateMap.get(word);
+ return nextState == null ? _nextStateMap.get(TopicWord.ANY_WORD) : nextState;
+ }
+
+ public Collection<TopicMatcherResult> terminate()
+ {
+ return _results;
+ }
+
+
+ public Collection<TopicMatcherResult> parse(TopicWordDictionary dictionary, AMQShortString routingKey)
+ {
+ return parse(dictionary, routingKey.tokenize(TOPIC_DELIMITTER));
+ }
+
+ private Collection<TopicMatcherResult> parse(final TopicWordDictionary dictionary,
+ final AMQShortStringTokenizer tokens)
+ {
+ if(!tokens.hasMoreTokens())
+ {
+ return _results;
+ }
+ TopicWord word = dictionary.getWord(tokens.nextToken());
+ TopicMatcherDFAState nextState = _nextStateMap.get(word);
+ if(nextState == null && word != TopicWord.ANY_WORD)
+ {
+ nextState = _nextStateMap.get(TopicWord.ANY_WORD);
+ }
+ if(nextState == null)
+ {
+ return Collections.EMPTY_SET;
+ }
+ // Shortcut if we are at a looping terminal state
+ if((nextState == this) && (_nextStateMap.size() == 1) && _nextStateMap.containsKey(TopicWord.ANY_WORD))
+ {
+ return _results;
+ }
+
+ return nextState.parse(dictionary, tokens);
+
+ }
+
+
+ public TopicMatcherDFAState mergeStateMachines(TopicMatcherDFAState otherStateMachine)
+ {
+ Map<Set<TopicMatcherDFAState>, TopicMatcherDFAState> newStateMap= new HashMap<Set<TopicMatcherDFAState>, TopicMatcherDFAState>();
+
+ Collection<TopicMatcherResult> results;
+
+ if(_results.isEmpty())
+ {
+ results = otherStateMachine._results;
+ }
+ else if(otherStateMachine._results.isEmpty())
+ {
+ results = _results;
+ }
+ else
+ {
+ results = new HashSet<TopicMatcherResult>(_results);
+ results.addAll(otherStateMachine._results);
+ }
+
+
+ final Map<TopicWord, TopicMatcherDFAState> newNextStateMap = new HashMap<TopicWord, TopicMatcherDFAState>();
+
+ TopicMatcherDFAState newState = new TopicMatcherDFAState(newNextStateMap, results);
+
+
+ Set<TopicMatcherDFAState> oldStates = new HashSet<TopicMatcherDFAState>();
+ oldStates.add(this);
+ oldStates.add(otherStateMachine);
+
+ newStateMap.put(oldStates, newState);
+
+ mergeStateMachines(oldStates, newNextStateMap, newStateMap);
+
+ return newState;
+
+ }
+
+ private static void mergeStateMachines(
+ final Set<TopicMatcherDFAState> oldStates,
+ final Map<TopicWord, TopicMatcherDFAState> newNextStateMap,
+ final Map<Set<TopicMatcherDFAState>, TopicMatcherDFAState> newStateMap)
+ {
+ Map<TopicWord, Set<TopicMatcherDFAState>> nfaMap = new HashMap<TopicWord, Set<TopicMatcherDFAState>>();
+
+ for(TopicMatcherDFAState state : oldStates)
+ {
+ Map<TopicWord, TopicMatcherDFAState> map = state._nextStateMap;
+ for(Map.Entry<TopicWord, TopicMatcherDFAState> entry : map.entrySet())
+ {
+ Set<TopicMatcherDFAState> states = nfaMap.get(entry.getKey());
+ if(states == null)
+ {
+ states = new HashSet<TopicMatcherDFAState>();
+ nfaMap.put(entry.getKey(), states);
+ }
+ states.add(entry.getValue());
+ }
+ }
+
+ Set<TopicMatcherDFAState> anyWordStates = nfaMap.get(TopicWord.ANY_WORD);
+
+ for(Map.Entry<TopicWord, Set<TopicMatcherDFAState>> transition : nfaMap.entrySet())
+ {
+ Set<TopicMatcherDFAState> destinations = transition.getValue();
+
+ if(anyWordStates != null)
+ {
+ destinations.addAll(anyWordStates);
+ }
+
+ TopicMatcherDFAState nextState = newStateMap.get(destinations);
+ if(nextState == null)
+ {
+
+ if(destinations.size() == 1)
+ {
+ nextState = destinations.iterator().next();
+ newStateMap.put(destinations, nextState);
+ }
+ else
+ {
+ Collection<TopicMatcherResult> results;
+
+ Set<Collection<TopicMatcherResult>> resultSets = new HashSet<Collection<TopicMatcherResult>>();
+ for(TopicMatcherDFAState destination : destinations)
+ {
+ resultSets.add(destination._results);
+ }
+ resultSets.remove(Collections.EMPTY_SET);
+ if(resultSets.size() == 0)
+ {
+ results = Collections.EMPTY_SET;
+ }
+ else if(resultSets.size() == 1)
+ {
+ results = resultSets.iterator().next();
+ }
+ else
+ {
+ results = new HashSet<TopicMatcherResult>();
+ for(Collection<TopicMatcherResult> oldResult : resultSets)
+ {
+ results.addAll(oldResult);
+ }
+ }
+
+ final Map<TopicWord, TopicMatcherDFAState> nextStateMap = new HashMap<TopicWord, TopicMatcherDFAState>();
+
+ nextState = new TopicMatcherDFAState(nextStateMap, results);
+ newStateMap.put(destinations, nextState);
+
+ mergeStateMachines(
+ destinations,
+ nextStateMap,
+ newStateMap);
+
+
+ }
+
+
+ }
+ newNextStateMap.put(transition.getKey(),nextState);
+ }
+
+ // Remove redundant transitions where defined tokenWord has same action as ANY_WORD
+ TopicMatcherDFAState anyWordState = newNextStateMap.get(TopicWord.ANY_WORD);
+ if(anyWordState != null)
+ {
+ List<TopicWord> removeList = new ArrayList<TopicWord>();
+ for(Map.Entry<TopicWord,TopicMatcherDFAState> entry : newNextStateMap.entrySet())
+ {
+ if(entry.getValue() == anyWordState && entry.getKey() != TopicWord.ANY_WORD)
+ {
+ removeList.add(entry.getKey());
+ }
+ }
+ for(TopicWord removeKey : removeList)
+ {
+ newNextStateMap.remove(removeKey);
+ }
+ }
+
+
+
+ }
+
+
+ public String toString()
+ {
+ StringBuilder transitions = new StringBuilder();
+ for(Map.Entry<TopicWord, TopicMatcherDFAState> entry : _nextStateMap.entrySet())
+ {
+ transitions.append("[ ");
+ transitions.append(entry.getKey());
+ transitions.append("\t ->\t ");
+ transitions.append(entry.getValue()._id);
+ transitions.append(" ]\n");
+ }
+
+
+ return "[ State " + _id + " ]\n" + transitions + "\n";
+
+ }
+
+ public String reachableStates()
+ {
+ StringBuilder result = new StringBuilder("Start state: " + _id + "\n");
+
+ SortedSet<TopicMatcherDFAState> reachableStates =
+ new TreeSet<TopicMatcherDFAState>(new Comparator<TopicMatcherDFAState>()
+ {
+ public int compare(final TopicMatcherDFAState o1, final TopicMatcherDFAState o2)
+ {
+ return o1._id - o2._id;
+ }
+ });
+ reachableStates.add(this);
+
+ int count;
+
+ do
+ {
+ count = reachableStates.size();
+ Collection<TopicMatcherDFAState> originalStates = new ArrayList<TopicMatcherDFAState>(reachableStates);
+ for(TopicMatcherDFAState state : originalStates)
+ {
+ reachableStates.addAll(state._nextStateMap.values());
+ }
+ }
+ while(reachableStates.size() != count);
+
+
+
+ for(TopicMatcherDFAState state : reachableStates)
+ {
+ result.append(state.toString());
+ }
+
+ return result.toString();
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java
new file mode 100644
index 0000000000..71d30adfac
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java
@@ -0,0 +1,25 @@
+package org.apache.qpid.server.exchange.topic;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public interface TopicMatcherResult
+{
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java
new file mode 100644
index 0000000000..3e9facf412
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java
@@ -0,0 +1,613 @@
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.AMQShortStringTokenizer;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.io.IOException;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class TopicParser
+{
+ private static final byte TOPIC_DELIMITER = (byte)'.';
+
+ private final TopicWordDictionary _dictionary = new TopicWordDictionary();
+ private final AtomicReference<TopicMatcherDFAState> _stateMachine = new AtomicReference<TopicMatcherDFAState>();
+
+ private static class Position
+ {
+ private final TopicWord _word;
+ private final boolean _selfTransition;
+ private final int _position;
+ private final boolean _endState;
+ private boolean _followedByAnyLoop;
+
+
+ public Position(final int position, final TopicWord word, final boolean selfTransition, final boolean endState)
+ {
+ _position = position;
+ _word = word;
+ _selfTransition = selfTransition;
+ _endState = endState;
+ }
+
+
+ }
+
+ private static final Position ERROR_POSITION = new Position(Integer.MAX_VALUE,null, true, false);
+
+ private static class SimpleState
+ {
+ Set<Position> _positions;
+ Map<TopicWord, SimpleState> _nextState;
+ }
+
+
+ public void addBinding(AMQShortString bindingKey, TopicMatcherResult result)
+ {
+
+ TopicMatcherDFAState startingStateMachine;
+ TopicMatcherDFAState newStateMachine;
+
+ do
+ {
+ startingStateMachine = _stateMachine.get();
+ if(startingStateMachine == null)
+ {
+ newStateMachine = createStateMachine(bindingKey, result);
+ }
+ else
+ {
+ newStateMachine = startingStateMachine.mergeStateMachines(createStateMachine(bindingKey, result));
+ }
+
+ }
+ while(!_stateMachine.compareAndSet(startingStateMachine,newStateMachine));
+
+ }
+
+ public Collection<TopicMatcherResult> parse(AMQShortString routingKey)
+ {
+ TopicMatcherDFAState stateMachine = _stateMachine.get();
+ if(stateMachine == null)
+ {
+ return Collections.EMPTY_SET;
+ }
+ else
+ {
+ return stateMachine.parse(_dictionary,routingKey);
+ }
+ }
+
+
+ TopicMatcherDFAState createStateMachine(AMQShortString bindingKey, TopicMatcherResult result)
+ {
+ List<TopicWord> wordList = createTopicWordList(bindingKey);
+ int wildCards = 0;
+ for(TopicWord word : wordList)
+ {
+ if(word == TopicWord.WILDCARD_WORD)
+ {
+ wildCards++;
+ }
+ }
+ if(wildCards == 0)
+ {
+ TopicMatcherDFAState[] states = new TopicMatcherDFAState[wordList.size()+1];
+ states[states.length-1] = new TopicMatcherDFAState(Collections.EMPTY_MAP, Collections.singleton(result));
+ for(int i = states.length-2; i >= 0; i--)
+ {
+ states[i] = new TopicMatcherDFAState(Collections.singletonMap(wordList.get(i),states[i+1]),Collections.EMPTY_SET);
+
+ }
+ return states[0];
+ }
+ else if(wildCards == wordList.size())
+ {
+ Map<TopicWord,TopicMatcherDFAState> stateMap = new HashMap<TopicWord,TopicMatcherDFAState>();
+ TopicMatcherDFAState state = new TopicMatcherDFAState(stateMap, Collections.singleton(result));
+ stateMap.put(TopicWord.ANY_WORD, state);
+ return state;
+ }
+
+
+ int positionCount = wordList.size() - wildCards;
+
+ Position[] positions = new Position[positionCount+1];
+
+ int lastWord;
+
+ if(wordList.get(wordList.size()-1)== TopicWord.WILDCARD_WORD)
+ {
+ lastWord = wordList.size()-1;
+ positions[positionCount] = new Position(positionCount, TopicWord.ANY_WORD, true, true);
+ }
+ else
+ {
+ lastWord = wordList.size();
+ positions[positionCount] = new Position(positionCount, TopicWord.ANY_WORD, false, true);
+ }
+
+
+ int pos = 0;
+ int wordPos = 0;
+
+
+ while(wordPos < lastWord)
+ {
+ TopicWord word = wordList.get(wordPos++);
+
+ if(word == TopicWord.WILDCARD_WORD)
+ {
+ int nextWordPos = wordPos++;
+ word = wordList.get(nextWordPos);
+
+ positions[pos] = new Position(pos++,word,true,false);
+ }
+ else
+ {
+ positions[pos] = new Position(pos++,word,false,false);
+ }
+
+ }
+
+
+ for(int p = 0; p<positionCount; p++)
+ {
+ boolean followedByWildcards = true;
+
+ int n = p;
+ while(followedByWildcards && n<(positionCount+1))
+ {
+
+ if(positions[n]._selfTransition)
+ {
+ break;
+ }
+ else if(positions[n]._word!=TopicWord.ANY_WORD)
+ {
+ followedByWildcards = false;
+ }
+ n++;
+ }
+
+
+ positions[p]._followedByAnyLoop = followedByWildcards && (n!= positionCount+1);
+ }
+
+
+ // from each position you transition to a set of other positions.
+ // we approach this by examining steps of increasing length - so we
+ // look how far we can go from the start position in 1 word, 2 words, etc...
+
+ Map<Set<Position>,SimpleState> stateMap = new HashMap<Set<Position>,SimpleState>();
+
+
+ SimpleState state = new SimpleState();
+ state._positions = Collections.singleton( positions[0] );
+ stateMap.put(state._positions, state);
+
+ calculateNextStates(state, stateMap, positions);
+
+ SimpleState[] simpleStates = stateMap.values().toArray(new SimpleState[stateMap.size()]);
+ HashMap<TopicWord, TopicMatcherDFAState>[] dfaStateMaps = new HashMap[simpleStates.length];
+ Map<SimpleState, TopicMatcherDFAState> simple2DFAMap = new HashMap<SimpleState, TopicMatcherDFAState>();
+
+ for(int i = 0; i < simpleStates.length; i++)
+ {
+
+ Collection<TopicMatcherResult> results;
+ boolean endState = false;
+
+ for(Position p : simpleStates[i]._positions)
+ {
+ if(p._endState)
+ {
+ endState = true;
+ break;
+ }
+ }
+
+ if(endState)
+ {
+ results = Collections.singleton(result);
+ }
+ else
+ {
+ results = Collections.EMPTY_SET;
+ }
+
+ dfaStateMaps[i] = new HashMap<TopicWord, TopicMatcherDFAState>();
+ simple2DFAMap.put(simpleStates[i], new TopicMatcherDFAState(dfaStateMaps[i],results));
+
+ }
+ for(int i = 0; i < simpleStates.length; i++)
+ {
+ SimpleState simpleState = simpleStates[i];
+
+ Map<TopicWord, SimpleState> nextSimpleStateMap = simpleState._nextState;
+ for(Map.Entry<TopicWord, SimpleState> stateMapEntry : nextSimpleStateMap.entrySet())
+ {
+ dfaStateMaps[i].put(stateMapEntry.getKey(), simple2DFAMap.get(stateMapEntry.getValue()));
+ }
+
+ }
+
+ return simple2DFAMap.get(state);
+
+ }
+
+
+
+ private void calculateNextStates(final SimpleState state,
+ final Map<Set<Position>, SimpleState> stateMap,
+ final Position[] positions)
+ {
+ Map<TopicWord, Set<Position>> transitions = new HashMap<TopicWord,Set<Position>>();
+
+ for(Position pos : state._positions)
+ {
+ if(pos._selfTransition)
+ {
+ Set<Position> dest = transitions.get(TopicWord.ANY_WORD);
+ if(dest == null)
+ {
+ dest = new HashSet<Position>();
+ transitions.put(TopicWord.ANY_WORD,dest);
+ }
+ dest.add(pos);
+ }
+
+ final int nextPos = pos._position + 1;
+ Position nextPosition = nextPos == positions.length ? ERROR_POSITION : positions[nextPos];
+
+ Set<Position> dest = transitions.get(pos._word);
+ if(dest == null)
+ {
+ dest = new HashSet<Position>();
+ transitions.put(pos._word,dest);
+ }
+ dest.add(nextPosition);
+
+ }
+
+ Set<Position> anyWordTransitions = transitions.get(TopicWord.ANY_WORD);
+ if(anyWordTransitions != null)
+ {
+ for(Set<Position> dest : transitions.values())
+ {
+ dest.addAll(anyWordTransitions);
+ }
+ }
+
+ state._nextState = new HashMap<TopicWord, SimpleState>();
+
+ for(Map.Entry<TopicWord,Set<Position>> dest : transitions.entrySet())
+ {
+
+ if(dest.getValue().size()>1)
+ {
+ dest.getValue().remove(ERROR_POSITION);
+ }
+ Position loopingTerminal = null;
+ for(Position destPos : dest.getValue())
+ {
+ if(destPos._selfTransition && destPos._endState)
+ {
+ loopingTerminal = destPos;
+ break;
+ }
+ }
+
+ if(loopingTerminal!=null)
+ {
+ dest.setValue(Collections.singleton(loopingTerminal));
+ }
+ else
+ {
+ Position anyLoop = null;
+ for(Position destPos : dest.getValue())
+ {
+ if(destPos._followedByAnyLoop)
+ {
+ if(anyLoop == null || anyLoop._position<destPos._position)
+ {
+ anyLoop = destPos;
+ }
+ }
+ }
+ if(anyLoop != null)
+ {
+ Collection<Position> removals = new ArrayList<Position>();
+ for(Position destPos : dest.getValue())
+ {
+ if(destPos._position < anyLoop._position)
+ {
+ removals.add(destPos);
+ }
+ }
+ dest.getValue().removeAll(removals);
+ }
+ }
+
+ SimpleState stateForEntry = stateMap.get(dest.getValue());
+ if(stateForEntry == null)
+ {
+ stateForEntry = new SimpleState();
+ stateForEntry._positions = dest.getValue();
+ stateMap.put(dest.getValue(),stateForEntry);
+ calculateNextStates(stateForEntry,
+ stateMap,
+ positions);
+ }
+ state._nextState.put(dest.getKey(),stateForEntry);
+
+
+
+ }
+
+ // remove redundant transitions
+ SimpleState anyWordState = state._nextState.get(TopicWord.ANY_WORD);
+ if(anyWordState != null)
+ {
+ List<TopicWord> removeList = new ArrayList<TopicWord>();
+ for(Map.Entry<TopicWord,SimpleState> entry : state._nextState.entrySet())
+ {
+ if(entry.getValue() == anyWordState && entry.getKey() != TopicWord.ANY_WORD)
+ {
+ removeList.add(entry.getKey());
+ }
+ }
+ for(TopicWord removeKey : removeList)
+ {
+ state._nextState.remove(removeKey);
+ }
+ }
+
+
+ }
+
+ private List<TopicWord> createTopicWordList(final AMQShortString bindingKey)
+ {
+ AMQShortStringTokenizer tokens = bindingKey.tokenize(TOPIC_DELIMITER);
+ TopicWord previousWord = null;
+
+ List<TopicWord> wordList = new ArrayList<TopicWord>();
+
+ while(tokens.hasMoreTokens())
+ {
+ TopicWord nextWord = _dictionary.getOrCreateWord(tokens.nextToken());
+ if(previousWord == TopicWord.WILDCARD_WORD)
+ {
+
+ if(nextWord == TopicWord.WILDCARD_WORD)
+ {
+ // consecutive wildcards can be merged
+ // i.e. subsequent wildcards can be discarded
+ continue;
+ }
+ else if(nextWord == TopicWord.ANY_WORD)
+ {
+ // wildcard and anyword can be reordered to always put anyword first
+ wordList.set(wordList.size()-1,TopicWord.ANY_WORD);
+ nextWord = TopicWord.WILDCARD_WORD;
+ }
+ }
+ wordList.add(nextWord);
+ previousWord = nextWord;
+
+ }
+ return wordList;
+ }
+
+
+ public static void main(String[] args)
+ {
+
+ printMatches("#.b.*.*.*.*.*.h.#.j.*.*.*.*.*.*.q.#.r.*.*.*.*.*.*.*.*","a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z");
+ printMatches(new String[]{
+ "#.a.#",
+ "#.b.#",
+ "#.c.#",
+ "#.d.#",
+ "#.e.#",
+ "#.f.#",
+ "#.g.#",
+ "#.h.#",
+ "#.i.#",
+ "#.j.#",
+ "#.k.#",
+ "#.l.#",
+ "#.m.#",
+ "#.n.#",
+ "#.o.#",
+ "#.p.#",
+ "#.q.#"
+
+ }, "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z");
+/*
+ printMatches(new String[]{
+ "#.a.#",
+ "#.b.#",
+ "#.c.#",
+ "#.d.#",
+ "#.e.#",
+ "#.f.#",
+ "#.g.#",
+ "#.h.#",
+ "#.i.#",
+ "#.j.#",
+ "#.k.#",
+ "#.l.#",
+ "#.m.#",
+ "#.n.#",
+ "#.o.#",
+ "#.p.#",
+ "#.q.#",
+ "#.r.#",
+ "#.s.#",
+ "#.t.#",
+ "#.u.#",
+ "#.v.#",
+ "#.w.#",
+ "#.x.#",
+ "#.y.#",
+ "#.z.#"
+
+
+ },"a.b");
+
+ printMatches("#.b.*.*.*.*.*.h.#.j.*.*.*.*.*.p.#.r.*.*.*.*.*","a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z");
+ printMatches("#.b.*.*.*.*.*.h.#.j.*.*.*.*.*.p.#.r.*.*.*.*.*.*.*.*","a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z");
+ printMatches("a.#.b.#","a.b.b.b.b.b.b.b.c");
+
+*/
+
+ printMatches("","");
+ printMatches("a","a");
+ printMatches("a","");
+ printMatches("","a");
+ printMatches("a.b","a.b");
+ printMatches("a","a.b");
+ printMatches("a.b","a");
+ printMatches("*","a");
+ printMatches("*.b","a.b");
+ printMatches("*.*","a.b");
+ printMatches("a.*","a.b");
+ printMatches("a.*.#","a.b");
+ printMatches("a.#.b","a.b");
+
+ printMatches("#.b","a");
+ printMatches("#.b","a.b");
+ printMatches("#.a.b","a.b");
+
+
+ printMatches("#","");
+ printMatches("#","a");
+ printMatches("#","a.b");
+ printMatches("#.#","a.b");
+ printMatches("#.*","a.b");
+
+ printMatches("#.a.b","a.b");
+ printMatches("a.b.#","a.b");
+ printMatches("a.#","a.b");
+ printMatches("#.*.#","a.b");
+ printMatches("#.*.b.#","a.b");
+ printMatches("#.a.*.#","a.b");
+ printMatches("#.a.#.b.#","a.b");
+ printMatches("#.*.#.*.#","a.b");
+ printMatches("*.#.*.#","a.b");
+ printMatches("#.*.#.*","a.b");
+
+
+ printMatches(new String[]{"a.#.b.#","a.*.#.b.#"},"a.b.b.b.b.b.b.b.c");
+
+
+ printMatches(new String[]{"a.b", "a.c"},"a.b");
+ printMatches(new String[]{"a.#", "a.c", "#.b"},"a.b");
+ printMatches(new String[]{"a.#", "a.c", "#.b", "#", "*.*"},"a.b");
+
+ printMatches(new String[]{"a.b.c.d.e.#", "a.b.c.d.#", "a.b.c.d.*", "a.b.c.#", "#.e", "a.*.c.d.e","#.c.*.#.*.*"},"a.b.c.d.e");
+ printMatches(new String[]{"a.b.c.d.e.#", "a.b.c.d.#", "a.b.c.d.*", "a.b.c.#", "#.e", "a.*.c.d.e","#.c.*.#.*.*"},"a.b.c.d.f.g");
+
+
+
+
+ }
+
+ private static void printMatches(final String[] bindingKeys, final String routingKey)
+ {
+ TopicMatcherDFAState sm = null;
+ Map<TopicMatcherResult, String> resultMap = new HashMap<TopicMatcherResult, String>();
+
+ TopicParser parser = new TopicParser();
+
+ long start = System.currentTimeMillis();
+ for(int i = 0; i < bindingKeys.length; i++)
+ {
+ System.out.println((System.currentTimeMillis() - start) + ":\t" + bindingKeys[i]);
+ TopicMatcherResult r = new TopicMatcherResult(){};
+ resultMap.put(r, bindingKeys[i]);
+ AMQShortString bindingKeyShortString = new AMQShortString(bindingKeys[i]);
+
+ System.err.println("=====================================================");
+ System.err.println("Adding binding key: " + bindingKeyShortString);
+ System.err.println("-----------------------------------------------------");
+
+
+ if(i==0)
+ {
+ sm = parser.createStateMachine(bindingKeyShortString, r);
+ }
+ else
+ {
+ sm = sm.mergeStateMachines(parser.createStateMachine(bindingKeyShortString, r));
+ }
+ System.err.println(sm.reachableStates());
+ System.err.println("=====================================================");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ }
+ AMQShortString routingKeyShortString = new AMQShortString(routingKey);
+
+ Collection<TopicMatcherResult> results = sm.parse(parser._dictionary, routingKeyShortString);
+ Collection<String> resultStrings = new ArrayList<String>();
+
+ for(TopicMatcherResult result : results)
+ {
+ resultStrings.add(resultMap.get(result));
+ }
+
+ final ArrayList<String> nonMatches = new ArrayList<String>(Arrays.asList(bindingKeys));
+ nonMatches.removeAll(resultStrings);
+ System.out.println("\""+routingKeyShortString+"\" matched with " + resultStrings + " DID NOT MATCH with " + nonMatches);
+
+
+ }
+
+ private static void printMatches(String bindingKey, String routingKey)
+ {
+ printMatches(new String[] { bindingKey }, routingKey);
+ }
+
+
+ private static boolean matches(String bindingKey, String routingKey)
+ {
+ AMQShortString bindingKeyShortString = new AMQShortString(bindingKey);
+ AMQShortString routingKeyShortString = new AMQShortString(routingKey);
+ TopicParser parser = new TopicParser();
+
+ final TopicMatcherResult result = new TopicMatcherResult(){};
+
+ TopicMatcherDFAState sm = parser.createStateMachine(bindingKeyShortString, result);
+ return !sm.parse(parser._dictionary,routingKeyShortString).isEmpty();
+
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java
new file mode 100644
index 0000000000..f14d70f8a1
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java
@@ -0,0 +1,54 @@
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public final class TopicWord
+{
+ public static final TopicWord ANY_WORD = new TopicWord("*");
+ public static final TopicWord WILDCARD_WORD = new TopicWord("#");
+ private String _word;
+
+ public TopicWord()
+ {
+
+ }
+
+ public TopicWord(String s)
+ {
+ _word = s;
+ }
+
+ public TopicWord(final AMQShortString name)
+ {
+ _word = name.toString();
+ }
+
+ public String toString()
+ {
+ return _word;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java
new file mode 100644
index 0000000000..65a0cd3107
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java
@@ -0,0 +1,63 @@
+package org.apache.qpid.server.exchange.topic;
+
+import org.apache.qpid.framing.AMQShortString;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class TopicWordDictionary
+{
+ private final ConcurrentHashMap<AMQShortString,TopicWord> _dictionary =
+ new ConcurrentHashMap<AMQShortString,TopicWord>();
+
+
+
+ public TopicWordDictionary()
+ {
+ _dictionary.put(new AMQShortString("*"), TopicWord.ANY_WORD);
+ _dictionary.put(new AMQShortString("#"), TopicWord.WILDCARD_WORD);
+ }
+
+
+
+
+ public TopicWord getOrCreateWord(AMQShortString name)
+ {
+ TopicWord word = _dictionary.putIfAbsent(name, new TopicWord(name));
+ if(word == null)
+ {
+ word = _dictionary.get(name);
+ }
+ return word;
+ }
+
+
+ public TopicWord getWord(AMQShortString name)
+ {
+ TopicWord word = _dictionary.get(name);
+ if(word == null)
+ {
+ word = TopicWord.ANY_WORD;
+ }
+ return word;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
index fb5220f4da..a964bce306 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/ArithmeticExpression.java
@@ -21,12 +21,12 @@ package org.apache.qpid.server.filter;
//
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* An expression which performs an operation on two expression values
*/
-public abstract class ArithmeticExpression extends BinaryExpression
+public abstract class ArithmeticExpression<E extends Exception> extends BinaryExpression<E>
{
protected static final int INTEGER = 1;
@@ -248,7 +248,7 @@ public abstract class ArithmeticExpression extends BinaryExpression
}
}
- public Object evaluate(AMQMessage message) throws AMQException
+ public Object evaluate(Filterable<E> message) throws E
{
Object lvalue = left.evaluate(message);
if (lvalue == null)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
index 024257bea9..7308de80d6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/BinaryExpression.java
@@ -23,23 +23,23 @@ package org.apache.qpid.server.filter;
/**
* An expression which performs an operation on two expression values.
*/
-public abstract class BinaryExpression implements Expression
+public abstract class BinaryExpression<E extends Exception> implements Expression<E>
{
- protected Expression left;
- protected Expression right;
+ protected Expression<E> left;
+ protected Expression<E> right;
- public BinaryExpression(Expression left, Expression right)
+ public BinaryExpression(Expression<E> left, Expression<E> right)
{
this.left = left;
this.right = right;
}
- public Expression getLeft()
+ public Expression<E> getLeft()
{
return left;
}
- public Expression getRight()
+ public Expression<E> getRight()
{
return right;
}
@@ -90,7 +90,7 @@ public abstract class BinaryExpression implements Expression
/**
* @param expression
*/
- public void setRight(Expression expression)
+ public void setRight(Expression<E> expression)
{
right = expression;
}
@@ -98,7 +98,7 @@ public abstract class BinaryExpression implements Expression
/**
* @param expression
*/
- public void setLeft(Expression expression)
+ public void setLeft(Expression<E> expression)
{
left = expression;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
index e28ff79820..9beb9798d0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/BooleanExpression.java
@@ -22,19 +22,20 @@ package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* A BooleanExpression is an expression that always
* produces a Boolean result.
*/
-public interface BooleanExpression extends Expression
+public interface BooleanExpression<E extends Exception> extends Expression<E>
{
/**
* @param message
* @return true if the expression evaluates to Boolean.TRUE.
- * @throws AMQException
+ * @throws E
*/
- public boolean matches(AMQMessage message) throws AMQException;
+ public boolean matches(Filterable<E> message) throws E;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
index 44281a3aae..921005c462 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/ComparisonExpression.java
@@ -28,21 +28,21 @@ import java.util.List;
import java.util.regex.Pattern;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* A filter performing a comparison of two objects
*/
-public abstract class ComparisonExpression extends BinaryExpression implements BooleanExpression
+public abstract class ComparisonExpression<E extends Exception> extends BinaryExpression<E> implements BooleanExpression<E>
{
- public static BooleanExpression createBetween(Expression value, Expression left, Expression right)
+ public static<E extends Exception> BooleanExpression<E> createBetween(Expression<E> value, Expression left, Expression<E> right)
{
return LogicExpression.createAND(createGreaterThanEqual(value, left), createLessThanEqual(value, right));
}
- public static BooleanExpression createNotBetween(Expression value, Expression left, Expression right)
+ public static<E extends Exception> BooleanExpression<E> createNotBetween(Expression<E> value, Expression<E> left, Expression<E> right)
{
return LogicExpression.createOR(createLessThan(value, left), createGreaterThan(value, right));
}
@@ -73,7 +73,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
REGEXP_CONTROL_CHARS.add(new Character('!'));
}
- static class LikeExpression extends UnaryExpression implements BooleanExpression
+ static class LikeExpression<E extends Exception> extends UnaryExpression<E> implements BooleanExpression<E>
{
Pattern likePattern;
@@ -81,7 +81,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
/**
* @param right
*/
- public LikeExpression(Expression right, String like, int escape)
+ public LikeExpression(Expression<E> right, String like, int escape)
{
super(right);
@@ -138,7 +138,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
/**
* org.apache.activemq.filter.Expression#evaluate(MessageEvaluationContext)
*/
- public Object evaluate(AMQMessage message) throws AMQException
+ public Object evaluate(Filterable<E> message) throws E
{
Object rv = this.getRight().evaluate(message);
@@ -148,11 +148,6 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
return null;
}
- if(rv instanceof AMQShortString)
- {
- rv = rv.toString();
- }
-
if (!(rv instanceof String))
{
return
@@ -163,7 +158,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
return likePattern.matcher((String) rv).matches() ? Boolean.TRUE : Boolean.FALSE;
}
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable<E> message) throws E
{
Object object = evaluate(message);
@@ -241,45 +236,9 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
return doCreateEqual(left, right);
}
- private static BooleanExpression doCreateEqual(Expression left, Expression right)
+ private static<E extends Exception> BooleanExpression<E> doCreateEqual(Expression<E> left, Expression<E> right)
{
- return new ComparisonExpression(left, right)
- {
-
- public Object evaluate(AMQMessage message) throws AMQException
- {
- Object lv = left.evaluate(message);
- Object rv = right.evaluate(message);
-
- // Iff one of the values is null
- if ((lv == null) ^ (rv == null))
- {
- return Boolean.FALSE;
- }
-
- if ((lv == rv) || lv.equals(rv))
- {
- return Boolean.TRUE;
- }
-
- if ((lv instanceof Comparable) && (rv instanceof Comparable))
- {
- return compare((Comparable) lv, (Comparable) rv);
- }
-
- return Boolean.FALSE;
- }
-
- protected boolean asBoolean(int answer)
- {
- return answer == 0;
- }
-
- public String getExpressionSymbol()
- {
- return "=";
- }
- };
+ return new EqualExpression(left, right);
}
public static BooleanExpression createGreaterThan(final Expression left, final Expression right)
@@ -429,7 +388,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
super(left, right);
}
- public Object evaluate(AMQMessage message) throws AMQException
+ public Object evaluate(Filterable<E> message) throws E
{
Comparable lv = (Comparable) left.evaluate(message);
if (lv == null)
@@ -454,40 +413,7 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
// try to convert up to allow the comparison.
if (lc != rc)
{
- if(lc == AMQShortString.class)
- {
- if(rc == String.class)
- {
- rv = new AMQShortString((String) rv);
-
- if(right instanceof ConstantExpression)
- {
- ((ConstantExpression)right).setValue(rv);
- }
- }
- else
- {
- return Boolean.FALSE;
- }
- }
- else if(lc == String.class)
- {
- if(rc == AMQShortString.class)
- {
- lv = new AMQShortString((String) lv);
-
- if(left instanceof ConstantExpression)
- {
- ((ConstantExpression)left).setValue(lv);
- }
- }
- else
- {
- return Boolean.FALSE;
- }
-
- }
- else if (lc == Byte.class)
+ if (lc == Byte.class)
{
if (rc == Short.class)
{
@@ -624,11 +550,52 @@ public abstract class ComparisonExpression extends BinaryExpression implements B
protected abstract boolean asBoolean(int answer);
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable<E> message) throws E
{
Object object = evaluate(message);
return (object != null) && (object == Boolean.TRUE);
}
+ private static class EqualExpression<E extends Exception> extends ComparisonExpression<E>
+ {
+ public EqualExpression(final Expression<E> left, final Expression<E> right)
+ {
+ super(left, right);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ Object lv = left.evaluate(message);
+ Object rv = right.evaluate(message);
+
+ // Iff one of the values is null
+ if ((lv == null) ^ (rv == null))
+ {
+ return Boolean.FALSE;
+ }
+
+ if ((lv == rv) || lv.equals(rv))
+ {
+ return Boolean.TRUE;
+ }
+
+ if ((lv instanceof Comparable) && (rv instanceof Comparable))
+ {
+ return compare((Comparable) lv, (Comparable) rv);
+ }
+
+ return Boolean.FALSE;
+ }
+
+ protected boolean asBoolean(int answer)
+ {
+ return answer == 0;
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "=";
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
index 73c4c66ad7..3ed2286f2e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/ConstantExpression.java
@@ -26,23 +26,23 @@ package org.apache.qpid.server.filter;
import java.math.BigDecimal;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* Represents a constant expression
*/
-public class ConstantExpression implements Expression
+public class ConstantExpression<E extends Exception> implements Expression<E>
{
- static class BooleanConstantExpression extends ConstantExpression implements BooleanExpression
+ static class BooleanConstantExpression<E extends Exception> extends ConstantExpression<E> implements BooleanExpression<E>
{
public BooleanConstantExpression(Object value)
{
super(value);
}
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable<E> message) throws E
{
Object object = evaluate(message);
@@ -121,7 +121,7 @@ public class ConstantExpression implements Expression
this.value = value;
}
- public Object evaluate(AMQMessage message) throws AMQException
+ public Object evaluate(Filterable<E> message) throws E
{
return value;
}
@@ -131,12 +131,6 @@ public class ConstantExpression implements Expression
return value;
}
- public void setValue(final Object value)
- {
- this.value = value;
- }
-
-
/**
* @see java.lang.Object#toString()
*/
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
index 5f646c15db..f2ebe41d26 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/Expression.java
@@ -22,16 +22,17 @@ package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* Represents an expression
*/
-public interface Expression
+public interface Expression<E extends Exception>
{
/**
* @return the value of this expression
*/
- public Object evaluate(AMQMessage message) throws AMQException;
+ public Object evaluate(Filterable<E> message) throws E;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java b/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
index c82de9fa15..dd3c126ee5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManager.java
@@ -24,14 +24,16 @@ package org.apache.qpid.server.filter;
//
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
+import org.apache.qpid.AMQException;
-public interface FilterManager
+public interface FilterManager<E extends Exception>
{
- void add(MessageFilter filter);
+ void add(MessageFilter<E> filter);
- void remove(MessageFilter filter);
+ void remove(MessageFilter<E> filter);
- boolean allAllow(AMQMessage msg);
+ boolean allAllow(Filterable<E> msg);
boolean hasFilters();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java
index 311f0680ec..a7f49d0566 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java
@@ -39,7 +39,7 @@ public class FilterManagerFactory
if (filters != null)
{
- manager = new SimpleFilterManager();
+
if(filters.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()))
{
@@ -47,23 +47,13 @@ public class FilterManagerFactory
if (selector != null && !selector.equals(""))
{
+ manager = new SimpleFilterManager();
manager.add(new JMSSelectorFilter(selector));
}
}
- if (filters.containsKey(AMQPFilterTypes.NO_CONSUME.getValue()))
- {
- manager.add(new NoConsumerFilter());
- }
-
-
- //If we added no filters don't bear the overhead of having an filter manager
- if (!manager.hasFilters())
- {
- manager = null;
- }
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java b/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
index 48b6602bda..96c9353872 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java
@@ -23,45 +23,30 @@ package org.apache.qpid.server.filter;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.filter.jms.selector.SelectorParser;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
-
-public class JMSSelectorFilter implements MessageFilter
+public class JMSSelectorFilter<E extends Exception> implements MessageFilter<E>
{
private final static Logger _logger = org.apache.log4j.Logger.getLogger(JMSSelectorFilter.class);
private String _selector;
- private BooleanExpression _matcher;
+ private BooleanExpression<E> _matcher;
public JMSSelectorFilter(String selector) throws AMQException
{
_selector = selector;
- _logger.info("Created JMSSelectorFilter with selector:" + _selector);
-
-
_matcher = new SelectorParser().parse(selector);
-
-
}
- public boolean matches(AMQMessage message)
+ public boolean matches(Filterable<E> message) throws E
{
- try
- {
- boolean match = _matcher.matches(message);
- if(_logger.isDebugEnabled())
- {
- _logger.debug(message + " match(" + match + ") selector(" + System.identityHashCode(_selector) + "):" + _selector);
- }
- return match;
- }
- catch (AMQException e)
+ boolean match = _matcher.matches(message);
+ if(_logger.isDebugEnabled())
{
- //fixme this needs to be sorted.. it shouldn't happen
- e.printStackTrace();
+ _logger.debug(message + " match(" + match + ") selector(" + System.identityHashCode(_selector) + "):" + _selector);
}
- return false;
+ return match;
}
public String getSelector()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
index c8cbdb2125..094363ed9a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/LogicExpression.java
@@ -22,71 +22,22 @@ package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* A filter performing a comparison of two objects
*/
-public abstract class LogicExpression extends BinaryExpression implements BooleanExpression
+public abstract class LogicExpression<E extends Exception> extends BinaryExpression<E> implements BooleanExpression<E>
{
- public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue)
+ public static<E extends Exception> BooleanExpression createOR(BooleanExpression<E> lvalue, BooleanExpression<E> rvalue)
{
- return new LogicExpression(lvalue, rvalue)
- {
-
- public Object evaluate(AMQMessage message) throws AMQException
- {
-
- Boolean lv = (Boolean) left.evaluate(message);
- // Can we do an OR shortcut??
- if ((lv != null) && lv.booleanValue())
- {
- return Boolean.TRUE;
- }
-
- Boolean rv = (Boolean) right.evaluate(message);
-
- return (rv == null) ? null : rv;
- }
-
- public String getExpressionSymbol()
- {
- return "OR";
- }
- };
+ return new OrExpression(lvalue, rvalue);
}
- public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue)
+ public static<E extends Exception> BooleanExpression createAND(BooleanExpression<E> lvalue, BooleanExpression<E> rvalue)
{
- return new LogicExpression(lvalue, rvalue)
- {
-
- public Object evaluate(AMQMessage message) throws AMQException
- {
-
- Boolean lv = (Boolean) left.evaluate(message);
-
- // Can we do an AND shortcut??
- if (lv == null)
- {
- return null;
- }
-
- if (!lv.booleanValue())
- {
- return Boolean.FALSE;
- }
-
- Boolean rv = (Boolean) right.evaluate(message);
-
- return (rv == null) ? null : rv;
- }
-
- public String getExpressionSymbol()
- {
- return "AND";
- }
- };
+ return new AndExpression(lvalue, rvalue);
}
/**
@@ -98,13 +49,74 @@ public abstract class LogicExpression extends BinaryExpression implements Boolea
super(left, right);
}
- public abstract Object evaluate(AMQMessage message) throws AMQException;
+ public abstract Object evaluate(Filterable<E> message) throws E;
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable<E> message) throws E
{
Object object = evaluate(message);
return (object != null) && (object == Boolean.TRUE);
}
+ private static class OrExpression<E extends Exception> extends LogicExpression<E>
+ {
+ public OrExpression(final BooleanExpression<E> lvalue, final BooleanExpression<E> rvalue)
+ {
+ super(lvalue, rvalue);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ Boolean lv = (Boolean) left.evaluate(message);
+ // Can we do an OR shortcut??
+ if ((lv != null) && lv.booleanValue())
+ {
+ return Boolean.TRUE;
+ }
+
+ Boolean rv = (Boolean) right.evaluate(message);
+
+ return (rv == null) ? null : rv;
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "OR";
+ }
+ }
+
+ private static class AndExpression<E extends Exception> extends LogicExpression<E>
+ {
+ public AndExpression(final BooleanExpression<E> lvalue, final BooleanExpression<E> rvalue)
+ {
+ super(lvalue, rvalue);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ Boolean lv = (Boolean) left.evaluate(message);
+
+ // Can we do an AND shortcut??
+ if (lv == null)
+ {
+ return null;
+ }
+
+ if (!lv.booleanValue())
+ {
+ return Boolean.FALSE;
+ }
+
+ Boolean rv = (Boolean) right.evaluate(message);
+
+ return (rv == null) ? null : rv;
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "AND";
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java b/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
index e6bfe974d5..58fc55f8e6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/MessageFilter.java
@@ -22,8 +22,9 @@ package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
-public interface MessageFilter
+public interface MessageFilter<E extends Exception>
{
- boolean matches(AMQMessage message) throws AMQException;
+ boolean matches(Filterable<E> message) throws E;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/NoConsumerFilter.java b/java/broker/src/main/java/org/apache/qpid/server/filter/NoConsumerFilter.java
index 47ca930d12..f1b3b2511d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/NoConsumerFilter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/NoConsumerFilter.java
@@ -22,7 +22,7 @@ package org.apache.qpid.server.filter;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
public class NoConsumerFilter implements MessageFilter
{
@@ -34,7 +34,7 @@ public class NoConsumerFilter implements MessageFilter
_logger.info("Created NoConsumerFilter");
}
- public boolean matches(AMQMessage message)
+ public boolean matches(Filterable message)
{
return true;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
index e5e9acf9bb..b30c70dac3 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
@@ -30,12 +30,12 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.CommonContentHeaderProperties;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* Represents a property expression
*/
-public class PropertyExpression implements Expression
+public class PropertyExpression<E extends Exception> implements Expression<E>
{
// Constants - defined the same as JMS
private static final int NON_PERSISTENT = 1;
@@ -44,223 +44,60 @@ public class PropertyExpression implements Expression
private static final Logger _logger = org.apache.log4j.Logger.getLogger(PropertyExpression.class);
- private static final HashMap<String, Expression> JMS_PROPERTY_EXPRESSIONS = new HashMap<String, Expression>();
+ private static final HashMap<String, Expression<? extends Exception>> JMS_PROPERTY_EXPRESSIONS = new HashMap<String, Expression<? extends Exception>>();
- static
{
- JMS_PROPERTY_EXPRESSIONS.put("JMSDestination", new Expression()
+ JMS_PROPERTY_EXPRESSIONS.put("JMSDestination", new Expression<E>()
{
- public Object evaluate(AMQMessage message)
+ public Object evaluate(Filterable<E> message)
{
//TODO
return null;
}
});
- JMS_PROPERTY_EXPRESSIONS.put("JMSReplyTo", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString replyTo = _properties.getReplyTo();
-
- return (replyTo == null) ? null : replyTo;
- }
- catch (AMQException e)
- {
- _logger.warn(e);
-
- return null;
- }
-
- }
-
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("JMSType", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString type = _properties.getType();
-
- return (type == null) ? null : type;
- }
- catch (AMQException e)
- {
- _logger.warn(e);
-
- return null;
- }
-
- }
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("JMSDeliveryMode", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
- try
- {
- int mode = message.isPersistent() ? PERSISTENT : NON_PERSISTENT;
- if (_logger.isDebugEnabled())
- {
- _logger.debug("JMSDeliveryMode is :" + mode);
- }
-
- return mode;
- }
- catch (AMQException e)
- {
- _logger.warn(e);
- }
-
- return NON_PERSISTENT;
- }
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("JMSPriority", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
-
- return (int) _properties.getPriority();
- }
- catch (AMQException e)
- {
- _logger.warn(e);
- }
-
- return DEFAULT_PRIORITY;
- }
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("AMQMessageID", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
-
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString messageId = _properties.getMessageId();
-
- return (messageId == null) ? null : messageId;
- }
- catch (AMQException e)
- {
- _logger.warn(e);
-
- return null;
- }
-
- }
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("JMSTimestamp", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
-
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
-
- return _properties.getTimestamp();
- }
- catch (AMQException e)
- {
- _logger.warn(e);
-
- return null;
- }
-
- }
- });
-
- JMS_PROPERTY_EXPRESSIONS.put("JMSCorrelationID", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
-
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
- AMQShortString correlationId = _properties.getCorrelationId();
-
- return (correlationId == null) ? null : correlationId;
- }
- catch (AMQException e)
- {
- _logger.warn(e);
+ JMS_PROPERTY_EXPRESSIONS.put("JMSReplyTo", new ReplyToExpression());
- return null;
- }
+ JMS_PROPERTY_EXPRESSIONS.put("JMSType", new TypeExpression());
- }
- });
+ JMS_PROPERTY_EXPRESSIONS.put("JMSDeliveryMode", new DeliveryModeExpression());
- JMS_PROPERTY_EXPRESSIONS.put("JMSExpiration", new Expression()
- {
- public Object evaluate(AMQMessage message)
- {
+ JMS_PROPERTY_EXPRESSIONS.put("JMSPriority", new PriorityExpression());
- try
- {
- CommonContentHeaderProperties _properties =
- (CommonContentHeaderProperties)
- message.getContentHeaderBody().properties;
+ JMS_PROPERTY_EXPRESSIONS.put("AMQMessageID", new MessageIDExpression());
- return _properties.getExpiration();
- }
- catch (AMQException e)
- {
- _logger.warn(e);
+ JMS_PROPERTY_EXPRESSIONS.put("JMSTimestamp", new TimestampExpression());
- return null;
- }
+ JMS_PROPERTY_EXPRESSIONS.put("JMSCorrelationID", new CorrelationIdExpression());
- }
- });
+ JMS_PROPERTY_EXPRESSIONS.put("JMSExpiration", new ExpirationExpression());
- JMS_PROPERTY_EXPRESSIONS.put("JMSRedelivered", new Expression()
+ JMS_PROPERTY_EXPRESSIONS.put("JMSRedelivered", new Expression<E>()
{
- public Object evaluate(AMQMessage message)
+ public Object evaluate(Filterable message) throws E
{
return message.isRedelivered();
}
});
-
}
- private final AMQShortString name;
- private final Expression jmsPropertyExpression;
+ private final String name;
+ private final Expression<E> jmsPropertyExpression;
+
+ public boolean outerTest()
+ {
+ return false;
+ }
public PropertyExpression(String name)
{
- this.name = new AMQShortString(name);
- jmsPropertyExpression = JMS_PROPERTY_EXPRESSIONS.get(name);
+ this.name = name;
+
+
+
+ jmsPropertyExpression = (Expression<E>) JMS_PROPERTY_EXPRESSIONS.get(name);
}
- public Object evaluate(AMQMessage message) throws AMQException
+ public Object evaluate(Filterable<E> message) throws E
{
if (jmsPropertyExpression != null)
@@ -283,7 +120,7 @@ public class PropertyExpression implements Expression
}
}
- public AMQShortString getName()
+ public String getName()
{
return name;
}
@@ -293,7 +130,7 @@ public class PropertyExpression implements Expression
*/
public String toString()
{
- return name.toString();
+ return name;
}
/**
@@ -319,4 +156,113 @@ public class PropertyExpression implements Expression
}
+ private static class ReplyToExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+ AMQShortString replyTo = _properties.getReplyTo();
+
+ return (replyTo == null) ? null : replyTo.toString();
+
+ }
+
+ }
+
+ private static class TypeExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+ AMQShortString type = _properties.getType();
+
+ return (type == null) ? null : type.toString();
+
+ }
+ }
+
+ private static class DeliveryModeExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ int mode = message.isPersistent() ? PERSISTENT : NON_PERSISTENT;
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("JMSDeliveryMode is :" + mode);
+ }
+
+ return mode;
+ }
+ }
+
+ private static class PriorityExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+
+ return (int) _properties.getPriority();
+ }
+ }
+
+ private static class MessageIDExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+ AMQShortString messageId = _properties.getMessageId();
+
+ return (messageId == null) ? null : messageId;
+
+ }
+ }
+
+ private static class TimestampExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+
+ return _properties.getTimestamp();
+ }
+ }
+
+ private static class CorrelationIdExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+ AMQShortString correlationId = _properties.getCorrelationId();
+
+ return (correlationId == null) ? null : correlationId.toString();
+ }
+ }
+
+ private static class ExpirationExpression<E extends Exception> implements Expression<E>
+ {
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ CommonContentHeaderProperties _properties =
+ (CommonContentHeaderProperties)
+ message.getContentHeaderBody().properties;
+
+ return _properties.getExpiration();
+
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java b/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
index 62a45f5420..cb738e1489 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/SimpleFilterManager.java
@@ -25,32 +25,33 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
-public class SimpleFilterManager implements FilterManager
+public class SimpleFilterManager implements FilterManager<AMQException>
{
private final Logger _logger = Logger.getLogger(SimpleFilterManager.class);
- private final ConcurrentLinkedQueue<MessageFilter> _filters;
+ private final ConcurrentLinkedQueue<MessageFilter<AMQException>> _filters;
public SimpleFilterManager()
{
_logger.debug("Creating SimpleFilterManager");
- _filters = new ConcurrentLinkedQueue<MessageFilter>();
+ _filters = new ConcurrentLinkedQueue<MessageFilter<AMQException>>();
}
- public void add(MessageFilter filter)
+ public void add(MessageFilter<AMQException> filter)
{
_filters.add(filter);
}
- public void remove(MessageFilter filter)
+ public void remove(MessageFilter<AMQException> filter)
{
_filters.remove(filter);
}
- public boolean allAllow(AMQMessage msg)
+ public boolean allAllow(Filterable<AMQException> msg)
{
- for (MessageFilter filter : _filters)
+ for (MessageFilter<AMQException> filter : _filters)
{
try
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
index 83b4ed5358..799a38af5a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/UnaryExpression.java
@@ -30,45 +30,23 @@ import java.util.Iterator;
import java.util.List;
import org.apache.qpid.AMQException;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
/**
* An expression which performs an operation on two expression values
*/
-public abstract class UnaryExpression implements Expression
+public abstract class UnaryExpression<E extends Exception> implements Expression<E>
{
private static final BigDecimal BD_LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
- protected Expression right;
+ protected Expression<E> right;
- public static Expression createNegate(Expression left)
+ public static<E extends Exception> Expression<E> createNegate(Expression<E> left)
{
- return new UnaryExpression(left)
- {
- public Object evaluate(AMQMessage message) throws AMQException
- {
- Object rvalue = right.evaluate(message);
- if (rvalue == null)
- {
- return null;
- }
-
- if (rvalue instanceof Number)
- {
- return negate((Number) rvalue);
- }
-
- return null;
- }
-
- public String getExpressionSymbol()
- {
- return "-";
- }
- };
+ return new NegativeExpression(left);
}
- public static BooleanExpression createInExpression(PropertyExpression right, List elements, final boolean not)
+ public static<E extends Exception> BooleanExpression createInExpression(PropertyExpression<E> right, List elements, final boolean not)
{
// Use a HashSet if there are many elements.
@@ -88,81 +66,17 @@ public abstract class UnaryExpression implements Expression
final Collection inList = t;
- return new BooleanUnaryExpression(right)
- {
- public Object evaluate(AMQMessage message) throws AMQException
- {
-
- Object rvalue = right.evaluate(message);
- if (rvalue == null)
- {
- return null;
- }
-
- if (rvalue.getClass() != String.class)
- {
- return null;
- }
-
- if (((inList != null) && inList.contains(rvalue)) ^ not)
- {
- return Boolean.TRUE;
- }
- else
- {
- return Boolean.FALSE;
- }
-
- }
-
- public String toString()
- {
- StringBuffer answer = new StringBuffer();
- answer.append(right);
- answer.append(" ");
- answer.append(getExpressionSymbol());
- answer.append(" ( ");
-
- int count = 0;
- for (Iterator i = inList.iterator(); i.hasNext();)
- {
- Object o = (Object) i.next();
- if (count != 0)
- {
- answer.append(", ");
- }
-
- answer.append(o);
- count++;
- }
-
- answer.append(" )");
-
- return answer.toString();
- }
-
- public String getExpressionSymbol()
- {
- if (not)
- {
- return "NOT IN";
- }
- else
- {
- return "IN";
- }
- }
- };
+ return new InExpression(right, inList, not);
}
- abstract static class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression
+ abstract static class BooleanUnaryExpression<E extends Exception> extends UnaryExpression<E> implements BooleanExpression<E>
{
- public BooleanUnaryExpression(Expression left)
+ public BooleanUnaryExpression(Expression<E> left)
{
super(left);
}
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable<E> message) throws E
{
Object object = evaluate(message);
@@ -171,26 +85,9 @@ public abstract class UnaryExpression implements Expression
}
;
- public static BooleanExpression createNOT(BooleanExpression left)
+ public static<E extends Exception> BooleanExpression<E> createNOT(BooleanExpression<E> left)
{
- return new BooleanUnaryExpression(left)
- {
- public Object evaluate(AMQMessage message) throws AMQException
- {
- Boolean lvalue = (Boolean) right.evaluate(message);
- if (lvalue == null)
- {
- return null;
- }
-
- return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
- }
-
- public String getExpressionSymbol()
- {
- return "NOT";
- }
- };
+ return new NotExpression(left);
}
public static BooleanExpression createXPath(final String xpath)
@@ -203,36 +100,9 @@ public abstract class UnaryExpression implements Expression
return new XQueryExpression(xpath);
}
- public static BooleanExpression createBooleanCast(Expression left)
+ public static<E extends Exception> BooleanExpression createBooleanCast(Expression<E> left)
{
- return new BooleanUnaryExpression(left)
- {
- public Object evaluate(AMQMessage message) throws AMQException
- {
- Object rvalue = right.evaluate(message);
- if (rvalue == null)
- {
- return null;
- }
-
- if (!rvalue.getClass().equals(Boolean.class))
- {
- return Boolean.FALSE;
- }
-
- return ((Boolean) rvalue).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
- }
-
- public String toString()
- {
- return right.toString();
- }
-
- public String getExpressionSymbol()
- {
- return "";
- }
- };
+ return new BooleanCastExpression(left);
}
private static Number negate(Number left)
@@ -281,7 +151,7 @@ public abstract class UnaryExpression implements Expression
this.right = left;
}
- public Expression getRight()
+ public Expression<E> getRight()
{
return right;
}
@@ -334,4 +204,166 @@ public abstract class UnaryExpression implements Expression
*/
public abstract String getExpressionSymbol();
+ private static class NegativeExpression<E extends Exception> extends UnaryExpression<E>
+ {
+ public NegativeExpression(final Expression<E> left)
+ {
+ super(left);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ Object rvalue = right.evaluate(message);
+ if (rvalue == null)
+ {
+ return null;
+ }
+
+ if (rvalue instanceof Number)
+ {
+ return negate((Number) rvalue);
+ }
+
+ return null;
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "-";
+ }
+ }
+
+ private static class InExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ {
+ private final Collection _inList;
+ private final boolean _not;
+
+ public InExpression(final PropertyExpression<E> right, final Collection inList, final boolean not)
+ {
+ super(right);
+ _inList = inList;
+ _not = not;
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+
+ Object rvalue = right.evaluate(message);
+ if (rvalue == null)
+ {
+ return null;
+ }
+
+ if (rvalue.getClass() != String.class)
+ {
+ return null;
+ }
+
+ if (((_inList != null) && _inList.contains(rvalue)) ^ _not)
+ {
+ return Boolean.TRUE;
+ }
+ else
+ {
+ return Boolean.FALSE;
+ }
+
+ }
+
+ public String toString()
+ {
+ StringBuffer answer = new StringBuffer();
+ answer.append(right);
+ answer.append(" ");
+ answer.append(getExpressionSymbol());
+ answer.append(" ( ");
+
+ int count = 0;
+ for (Iterator i = _inList.iterator(); i.hasNext();)
+ {
+ Object o = (Object) i.next();
+ if (count != 0)
+ {
+ answer.append(", ");
+ }
+
+ answer.append(o);
+ count++;
+ }
+
+ answer.append(" )");
+
+ return answer.toString();
+ }
+
+ public String getExpressionSymbol()
+ {
+ if (_not)
+ {
+ return "NOT IN";
+ }
+ else
+ {
+ return "IN";
+ }
+ }
+ }
+
+ private static class NotExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ {
+ public NotExpression(final BooleanExpression<E> left)
+ {
+ super(left);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ Boolean lvalue = (Boolean) right.evaluate(message);
+ if (lvalue == null)
+ {
+ return null;
+ }
+
+ return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "NOT";
+ }
+ }
+
+ private static class BooleanCastExpression<E extends Exception> extends BooleanUnaryExpression<E>
+ {
+ public BooleanCastExpression(final Expression<E> left)
+ {
+ super(left);
+ }
+
+ public Object evaluate(Filterable<E> message) throws E
+ {
+ Object rvalue = right.evaluate(message);
+ if (rvalue == null)
+ {
+ return null;
+ }
+
+ if (!rvalue.getClass().equals(Boolean.class))
+ {
+ return Boolean.FALSE;
+ }
+
+ return ((Boolean) rvalue).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+ }
+
+ public String toString()
+ {
+ return right.toString();
+ }
+
+ public String getExpressionSymbol()
+ {
+ return "";
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
index f5454afae5..1311178fb1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/XPathExpression.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.filter;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -70,7 +71,7 @@ public final class XPathExpression implements BooleanExpression {
private final XPathEvaluator evaluator;
static public interface XPathEvaluator {
- public boolean evaluate(AMQMessage message) throws AMQException;
+ public boolean evaluate(Filterable message) throws AMQException;
}
XPathExpression(String xpath) {
@@ -92,7 +93,7 @@ public final class XPathExpression implements BooleanExpression {
}
}
- public Object evaluate(AMQMessage message) throws AMQException {
+ public Object evaluate(Filterable message) throws AMQException {
// try {
//FIXME this is flow to disk work
// if( message.isDropped() )
@@ -117,7 +118,7 @@ public final class XPathExpression implements BooleanExpression {
* @return true if the expression evaluates to Boolean.TRUE.
* @throws AMQException
*/
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable message) throws AMQException
{
Object object = evaluate(message);
return object!=null && object==Boolean.TRUE;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
index f5debb607a..c13f81cd08 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/XQueryExpression.java
@@ -19,6 +19,7 @@ package org.apache.qpid.server.filter;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
//
// Based on like named file from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
@@ -35,7 +36,7 @@ public final class XQueryExpression implements BooleanExpression {
this.xpath = xpath;
}
- public Object evaluate(AMQMessage message) throws AMQException {
+ public Object evaluate(Filterable message) throws AMQException {
return Boolean.FALSE;
}
@@ -48,7 +49,7 @@ public final class XQueryExpression implements BooleanExpression {
* @return true if the expression evaluates to Boolean.TRUE.
* @throws AMQException
*/
- public boolean matches(AMQMessage message) throws AMQException
+ public boolean matches(Filterable message) throws AMQException
{
Object object = evaluate(message);
return object!=null && object==Boolean.TRUE;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java b/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
index 35d770fd5d..cc67776682 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/XalanXPathEvaluator.java
@@ -29,6 +29,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.Filterable;
import org.apache.xpath.CachedXPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.traversal.NodeIterator;
@@ -42,7 +43,7 @@ public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator {
this.xpath = xpath;
}
- public boolean evaluate(AMQMessage m) throws AMQException
+ public boolean evaluate(Filterable m) throws AMQException
{
// TODO - we would have to check the content type and then evaluate the content
// here... is this really a feature we wish to implement? - RobG
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java
new file mode 100644
index 0000000000..895db7b15b
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/AbstractFlowCreditManager.java
@@ -0,0 +1,62 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.flow;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Set;
+import java.util.HashSet;
+
+public abstract class AbstractFlowCreditManager implements FlowCreditManager
+{
+ protected final AtomicBoolean _suspended = new AtomicBoolean(false);
+ private final Set<FlowCreditManagerListener> _listeners = new HashSet<FlowCreditManagerListener>();
+
+ public final void addStateListener(FlowCreditManagerListener listener)
+ {
+ _listeners.add(listener);
+ }
+
+ public final boolean removeListener(FlowCreditManagerListener listener)
+ {
+ return _listeners.remove(listener);
+ }
+
+ private void notifyListeners(final boolean suspended)
+ {
+ for(FlowCreditManagerListener listener : _listeners)
+ {
+ listener.creditStateChanged(!suspended);
+ }
+ }
+
+ protected final void setSuspended(final boolean suspended)
+ {
+ if(_suspended.compareAndSet(!suspended, suspended))
+ {
+ notifyListeners(suspended);
+ }
+ }
+
+ protected final void notifyIncreaseBytesCredit()
+ {
+ notifyListeners(false);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
new file mode 100644
index 0000000000..96a1071135
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
@@ -0,0 +1,77 @@
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Set;
+import java.util.HashSet;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class BytesOnlyCreditManager extends AbstractFlowCreditManager
+{
+ private final AtomicLong _bytesCredit;
+
+ public BytesOnlyCreditManager(long initialCredit)
+ {
+ _bytesCredit = new AtomicLong(initialCredit);
+ }
+
+ public void addCredit(long messageCredit, long bytesCredit)
+ {
+ _bytesCredit.addAndGet(bytesCredit);
+ setSuspended(false);
+ }
+
+ public void removeAllCredit()
+ {
+ _bytesCredit.set(0L);
+ }
+
+ public boolean hasCredit()
+ {
+ return _bytesCredit.get() > 0L;
+ }
+
+ public boolean useCreditForMessage(AMQMessage msg)
+ {
+ final long msgSize = msg.getSize();
+ if(hasCredit())
+ {
+ if(_bytesCredit.addAndGet(-msgSize) >= 0)
+ {
+ return true;
+ }
+ else
+ {
+ _bytesCredit.addAndGet(msgSize);
+ setSuspended(true);
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
new file mode 100644
index 0000000000..a249a6e63a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
@@ -0,0 +1,44 @@
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public interface FlowCreditManager
+{
+
+ public static interface FlowCreditManagerListener
+ {
+ void creditStateChanged(boolean hasCredit);
+ }
+
+ void addStateListener(FlowCreditManagerListener listener);
+
+ boolean removeListener(FlowCreditManagerListener listener);
+
+ public void addCredit(long messageCredit, long bytesCredit);
+
+ public void removeAllCredit();
+
+ public boolean hasCredit();
+
+ public boolean useCreditForMessage(AMQMessage msg);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
new file mode 100644
index 0000000000..d63431c3eb
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
@@ -0,0 +1,44 @@
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class LimitlessCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
+{
+ public void addCredit(long messageCredit, long bytesCredit)
+ {
+ }
+
+ public void removeAllCredit()
+ {
+ }
+
+ public boolean hasCredit()
+ {
+ return true;
+ }
+
+ public boolean useCreditForMessage(AMQMessage msg)
+ {
+ return true;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
new file mode 100644
index 0000000000..9c377481de
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
@@ -0,0 +1,79 @@
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class MessageAndBytesCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
+{
+ private long _messageCredit;
+ private long _bytesCredit;
+
+ MessageAndBytesCreditManager(final long messageCredit, final long bytesCredit)
+ {
+ _messageCredit = messageCredit;
+ _bytesCredit = bytesCredit;
+ }
+
+ public synchronized void addCredit(long messageCredit, long bytesCredit)
+ {
+ _messageCredit += messageCredit;
+ _bytesCredit += bytesCredit;
+ setSuspended(hasCredit());
+ }
+
+ public synchronized void removeAllCredit()
+ {
+ _messageCredit = 0L;
+ _bytesCredit = 0L;
+ setSuspended(true);
+ }
+
+ public synchronized boolean hasCredit()
+ {
+ return (_messageCredit > 0L) && ( _bytesCredit > 0L );
+ }
+
+ public synchronized boolean useCreditForMessage(AMQMessage msg)
+ {
+ if(_messageCredit == 0L)
+ {
+ setSuspended(true);
+ return false;
+ }
+ else
+ {
+ final long msgSize = msg.getSize();
+ if(msgSize > _bytesCredit)
+ {
+ setSuspended(true);
+ return false;
+ }
+ _messageCredit--;
+ _bytesCredit -= msgSize;
+ setSuspended(false);
+ return true;
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
new file mode 100644
index 0000000000..c1b3a09006
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
@@ -0,0 +1,76 @@
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class MessageOnlyCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
+{
+ private final AtomicLong _messageCredit;
+
+ public MessageOnlyCreditManager(final long initialCredit)
+ {
+ _messageCredit = new AtomicLong(initialCredit);
+ }
+
+ public void addCredit(long messageCredit, long bytesCredit)
+ {
+ setSuspended(false);
+ _messageCredit.addAndGet(messageCredit);
+ }
+
+ public void removeAllCredit()
+ {
+ setSuspended(true);
+ _messageCredit.set(0L);
+ }
+
+ public boolean hasCredit()
+ {
+ return _messageCredit.get() > 0L;
+ }
+
+ public boolean useCreditForMessage(AMQMessage msg)
+ {
+ if(hasCredit())
+ {
+ if(_messageCredit.addAndGet(-1L) >= 0)
+ {
+ setSuspended(false);
+ return true;
+ }
+ else
+ {
+ _messageCredit.addAndGet(1L);
+ setSuspended(true);
+ return false;
+ }
+ }
+ else
+ {
+ setSuspended(true);
+ return false;
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
new file mode 100644
index 0000000000..be0300f2c1
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
@@ -0,0 +1,185 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.flow;
+
+import org.apache.qpid.server.queue.AMQMessage;
+
+public class Pre0_10CreditManager extends AbstractFlowCreditManager implements FlowCreditManager
+{
+
+ private volatile long _bytesCreditLimit;
+ private volatile long _messageCreditLimit;
+
+ private volatile long _bytesCredit;
+ private volatile long _messageCredit;
+
+ public Pre0_10CreditManager(long bytesCreditLimit, long messageCreditLimit)
+ {
+ _bytesCreditLimit = bytesCreditLimit;
+ _messageCreditLimit = messageCreditLimit;
+ _bytesCredit = bytesCreditLimit;
+ _messageCredit = messageCreditLimit;
+ }
+
+
+ public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit)
+ {
+ long bytesCreditChange = bytesCreditLimit - _bytesCreditLimit;
+ long messageCreditChange = messageCreditLimit - _messageCreditLimit;
+
+
+
+ if(bytesCreditChange != 0L)
+ {
+ if(bytesCreditLimit == 0L)
+ {
+ _bytesCredit = 0;
+ }
+ else
+ {
+ _bytesCredit += bytesCreditChange;
+ }
+ }
+
+
+ if(messageCreditChange != 0L)
+ {
+ if(messageCreditLimit == 0L)
+ {
+ _messageCredit = 0;
+ }
+ else
+ {
+ _messageCredit += messageCreditChange;
+ }
+ }
+
+
+ _bytesCreditLimit = bytesCreditLimit;
+ _messageCreditLimit = messageCreditLimit;
+
+ setSuspended(!hasCredit());
+
+ }
+
+
+ public synchronized void addCredit(final long messageCredit, final long bytesCredit)
+ {
+ final long messageCreditLimit = _messageCreditLimit;
+ boolean notifyIncrease = true;
+ if(messageCreditLimit != 0L)
+ {
+ notifyIncrease = (_messageCredit != 0);
+ long newCredit = _messageCredit + messageCredit;
+ _messageCredit = newCredit > messageCreditLimit ? messageCreditLimit : newCredit;
+ }
+
+
+ final long bytesCreditLimit = _bytesCreditLimit;
+ if(bytesCreditLimit != 0L)
+ {
+ long newCredit = _bytesCredit + bytesCredit;
+ _bytesCredit = newCredit > bytesCreditLimit ? bytesCreditLimit : newCredit;
+ if(notifyIncrease && bytesCredit>0)
+ {
+ notifyIncreaseBytesCredit();
+ }
+ }
+
+
+
+ setSuspended(!hasCredit());
+
+ }
+
+ public synchronized void removeAllCredit()
+ {
+ _bytesCredit = 0L;
+ _messageCredit = 0L;
+ setSuspended(!hasCredit());
+ }
+
+ public synchronized boolean hasCredit()
+ {
+ return (_bytesCreditLimit == 0L || _bytesCredit > 0)
+ && (_messageCreditLimit == 0L || _messageCredit > 0);
+ }
+
+ public synchronized boolean useCreditForMessage(final AMQMessage msg)
+ {
+ if(_messageCreditLimit != 0L)
+ {
+ if(_messageCredit != 0L)
+ {
+ if(_bytesCreditLimit == 0L)
+ {
+ _messageCredit--;
+
+ return true;
+ }
+ else
+ {
+ if((_bytesCredit >= msg.getSize()) || (_bytesCredit == _bytesCreditLimit))
+ {
+ _messageCredit--;
+ _bytesCredit -= msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ setSuspended(true);
+ return false;
+ }
+ }
+ else
+ {
+ if(_bytesCreditLimit == 0L)
+ {
+
+ return true;
+ }
+ else
+ {
+ if((_bytesCredit >= msg.getSize()) || (_bytesCredit == _bytesCreditLimit))
+ {
+ _bytesCredit -= msg.getSize();
+
+ return true;
+ }
+ else
+ {
+ //setSuspended(true);
+ return false;
+ }
+ }
+
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
index 133c97a146..c13a69b793 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java
@@ -1,65 +1,40 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.AMQException;
-
-/**
- * @author Apache Software Foundation
- *
- *
- */
-public class AccessRequestHandler implements StateAwareMethodListener<AccessRequestBody>
-{
- private static final AccessRequestHandler _instance = new AccessRequestHandler();
-
-
- public static AccessRequestHandler getInstance()
- {
- return _instance;
- }
-
- private AccessRequestHandler()
- {
- }
-
- public void methodReceived(AMQStateManager stateManager, AccessRequestBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
- MethodRegistry methodRegistry = session.getMethodRegistry();
-
- // We don't implement access control class, but to keep clients happy that expect it
- // always use the "0" ticket.
- AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
-
- session.writeFrame(response.generateFrame(channelId));
- }
-}
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.AMQException;
+
+/**
+ * @author Apache Software Foundation
+ *
+ *
+ */
+public class AccessRequestHandler implements StateAwareMethodListener<AccessRequestBody>
+{
+ private static final AccessRequestHandler _instance = new AccessRequestHandler();
+
+
+ public static AccessRequestHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private AccessRequestHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, AccessRequestBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+
+ // We don't implement access control class, but to keep clients happy that expect it
+ // always use the "0" ticket.
+ AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
+
+ session.writeFrame(response.generateFrame(channelId));
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java
index bda1c16cf6..29054f55c1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java
@@ -21,11 +21,9 @@
package org.apache.qpid.server.handler;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.BasicCancelBody;
import org.apache.qpid.framing.BasicCancelOkBody;
import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.state.AMQStateManager;
@@ -65,7 +63,7 @@ public class BasicCancelMethodHandler implements StateAwareMethodListener<BasicC
" nowait:" + body.getNowait());
}
- channel.unsubscribeConsumer(session, body.getConsumerTag());
+ channel.unsubscribeConsumer(body.getConsumerTag());
if (!body.getNowait())
{
MethodRegistry methodRegistry = session.getMethodRegistry();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
index 7cd4afdb77..5342a7f518 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
@@ -111,7 +111,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
try
{
- AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, session, !body.getNoAck(),
+ AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(),
body.getArguments(), body.getNoLocal(), body.getExclusive());
if (!body.getNowait())
{
@@ -121,8 +121,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
}
- //now allow queue to start async processing of any backlog of messages
- queue.deliverAsync();
+
}
catch (org.apache.qpid.AMQInvalidArgumentException ise)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
index 3731116cba..be1135dd91 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
@@ -1,101 +1,187 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicGetBody;
-import org.apache.qpid.framing.BasicGetEmptyBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.Permission;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody>
-{
- private static final Logger _log = Logger.getLogger(BasicGetMethodHandler.class);
-
- private static final BasicGetMethodHandler _instance = new BasicGetMethodHandler();
-
- public static BasicGetMethodHandler getInstance()
- {
- return _instance;
- }
-
- private BasicGetMethodHandler()
- {
- }
-
- public void methodReceived(AMQStateManager stateManager, BasicGetBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
-
- VirtualHost vHost = session.getVirtualHost();
-
- AMQChannel channel = session.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
- else
- {
- AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue());
-
- if (queue == null)
- {
- _log.info("No queue for '" + body.getQueue() + "'");
- if(body.getQueue()!=null)
- {
- throw body.getConnectionException(AMQConstant.NOT_FOUND,
- "No such queue, '" + body.getQueue()+ "'");
- }
- else
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "No queue name provided, no default queue defined.");
- }
- }
- else
- {
-
- //Perform ACLs
- vHost.getAccessManager().authorise(session, Permission.CONSUME, body, queue);
-
- if (!queue.performGet(session, channel, !body.getNoAck()))
- {
- MethodRegistry methodRegistry = session.getMethodRegistry();
- // TODO - set clusterId
- BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
-
-
- session.writeFrame(responseBody.generateFrame(channelId));
- }
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.BasicGetBody;
+import org.apache.qpid.framing.BasicGetEmptyBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.MessageOnlyCreditManager;
+import org.apache.qpid.server.subscription.SubscriptionImpl;
+import org.apache.qpid.server.subscription.ClientDeliveryMethod;
+import org.apache.qpid.server.subscription.RecordDeliveryMethod;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.SimpleAMQQueue;
+import org.apache.qpid.server.security.access.Permission;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody>
+{
+ private static final Logger _log = Logger.getLogger(BasicGetMethodHandler.class);
+
+ private static final BasicGetMethodHandler _instance = new BasicGetMethodHandler();
+
+ public static BasicGetMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private BasicGetMethodHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, BasicGetBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+
+ VirtualHost vHost = session.getVirtualHost();
+
+ AMQChannel channel = session.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+ else
+ {
+ AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue());
+ if (queue == null)
+ {
+ _log.info("No queue for '" + body.getQueue() + "'");
+ if(body.getQueue()!=null)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_FOUND,
+ "No such queue, '" + body.getQueue()+ "'");
+ }
+ else
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "No queue name provided, no default queue defined.");
+ }
+ }
+ else
+ {
+
+ //Perform ACLs
+ vHost.getAccessManager().authorise(session, Permission.CONSUME, body, queue);
+
+ if (!performGet(queue,session, channel, !body.getNoAck()))
+ {
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ // TODO - set clusterId
+ BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
+
+
+ session.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }
+ }
+ }
+
+ public static boolean performGet(final AMQQueue queue,
+ final AMQProtocolSession session,
+ final AMQChannel channel,
+ final boolean acks)
+ throws AMQException
+ {
+
+ final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);
+
+ final ClientDeliveryMethod getDeliveryMethod = new ClientDeliveryMethod()
+ {
+
+ int _msg;
+
+ public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ throws AMQException
+ {
+ singleMessageCredit.useCreditForMessage(entry.getMessage());
+ session.getProtocolOutputConverter().writeGetOk(entry.getMessage(), channel.getChannelId(),
+ deliveryTag, queue.getMessageCount());
+
+ }
+ };
+ final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
+ {
+
+ public void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag)
+ {
+ channel.addUnacknowledgedMessage(entry, deliveryTag, null);
+ }
+ };
+
+ Subscription sub;
+ if(acks)
+ {
+ sub = SubscriptionFactoryImpl.INSTANCE.createSubscription(channel, session, null, acks, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod);
+ }
+ else
+ {
+ sub = new GetNoAckSubscription(channel,
+ session,
+ null,
+ null,
+ false,
+ singleMessageCredit,
+ getDeliveryMethod,
+ getRecordMethod);
+ }
+
+ queue.registerSubscription(sub,false);
+ queue.flushSubscription(sub);
+ queue.unregisterSubscription(sub);
+ return(!singleMessageCredit.hasCredit());
+
+
+ }
+
+ public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
+ {
+ public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ }
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return !getCreditManager().useCreditForMessage(msg.getMessage());
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java
index 0f99a21ee5..e8e42454de 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java
@@ -91,7 +91,7 @@ public class BasicPublishMethodHandler implements StateAwareMethodListener<Basic
MessagePublishInfo info = session.getMethodRegistry().getProtocolVersionMethodConverter().convertToInfo(body);
info.setExchange(exchange);
- channel.setPublishFrame(info, session, e);
+ channel.setPublishFrame(info, e);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java
index 3c95180dca..dd3281c65f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java
@@ -22,10 +22,8 @@ package org.apache.qpid.server.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicQosBody;
-import org.apache.qpid.framing.BasicQosOkBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
@@ -49,8 +47,8 @@ public class BasicQosHandler implements StateAwareMethodListener<BasicQosBody>
throw body.getChannelNotFoundException(channelId);
}
- channel.setPrefetchCount(body.getPrefetchCount());
- channel.setPrefetchSize(body.getPrefetchSize());
+ channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount());
+
MethodRegistry methodRegistry = session.getMethodRegistry();
AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
index bca35be535..15484273c8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java
@@ -1,75 +1,54 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.framing.BasicRecoverBody;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.framing.BasicRecoverSyncBody;
-import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
-import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.AMQException;
-
-public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<BasicRecoverSyncBody>
-{
- private static final Logger _logger = Logger.getLogger(BasicRecoverSyncMethodHandler.class);
-
- private static final BasicRecoverSyncMethodHandler _instance = new BasicRecoverSyncMethodHandler();
-
- public static BasicRecoverSyncMethodHandler getInstance()
- {
- return _instance;
- }
-
- public void methodReceived(AMQStateManager stateManager, BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
- _logger.debug("Recover received on protocol session " + session + " and channel " + channelId);
- AMQChannel channel = session.getChannel(channelId);
-
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
-
- channel.resend(body.getRequeue());
-
- // Qpid 0-8 hacks a synchronous -ok onto recover.
- // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
- if(session.getProtocolVersion().equals(ProtocolVersion.v0_9))
- {
- MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) session.getMethodRegistry();
- AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
- session.writeFrame(recoverOk.generateFrame(channelId));
-
- }
-
- }
-}
+package org.apache.qpid.server.handler;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.framing.BasicRecoverBody;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.BasicRecoverSyncBody;
+import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
+import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.AMQException;
+
+public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<BasicRecoverSyncBody>
+{
+ private static final Logger _logger = Logger.getLogger(BasicRecoverSyncMethodHandler.class);
+
+ private static final BasicRecoverSyncMethodHandler _instance = new BasicRecoverSyncMethodHandler();
+
+ public static BasicRecoverSyncMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ public void methodReceived(AMQStateManager stateManager, BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+ _logger.debug("Recover received on protocol session " + session + " and channel " + channelId);
+ AMQChannel channel = session.getChannel(channelId);
+
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+
+ channel.resend(body.getRequeue());
+
+ // Qpid 0-8 hacks a synchronous -ok onto recover.
+ // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
+ if(session.getProtocolVersion().equals(ProtocolVersion.v0_9))
+ {
+ MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) session.getMethodRegistry();
+ AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+ session.writeFrame(recoverOk.generateFrame(channelId));
+
+ }
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
index 069cc6ea2c..f3cab10ed7 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
@@ -22,9 +22,8 @@ package org.apache.qpid.server.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicRejectBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.ack.UnacknowledgedMessage;
+import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
@@ -49,16 +48,6 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
{
AMQProtocolSession session = stateManager.getProtocolSession();
-
-
-// if (_logger.isDebugEnabled())
-// {
-// _logger.debug("Rejecting:" + evt.getMethod().deliveryTag +
-// ": Requeue:" + evt.getMethod().requeue +
-//// ": Resend:" + evt.getMethod().resend +
-// " on channel:" + channelId);
-// }
-
AMQChannel channel = session.getChannel(channelId);
if (channel == null)
@@ -76,7 +65,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
long deliveryTag = body.getDeliveryTag();
- UnacknowledgedMessage message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
+ QueueEntry message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
if (message == null)
{
@@ -85,11 +74,16 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
}
else
{
- if (message.isQueueDeleted() || message.getQueue().isDeleted())
+ if (message.isQueueDeleted())
{
_logger.warn("Message's Queue as already been purged, unable to Reject. " +
"Dropping message should use Dead Letter Queue");
- //sendtoDeadLetterQueue(msg)
+ message = channel.getUnacknowledgedMessageMap().remove(deliveryTag);
+ if(message != null)
+ {
+ message.discard(channel.getStoreContext());
+ }
+ //sendtoDeadLetterQueue(msg)
return;
}
@@ -111,7 +105,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
// If we haven't requested message to be resent to this consumer then reject it from ever getting it.
//if (!evt.getMethod().resend)
{
- message.entry.reject();
+ message.reject();
}
if (body.getRequeue())
@@ -121,6 +115,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
else
{
_logger.warn("Dropping message as requeue not required and there is no dead letter queue");
+ message = channel.getUnacknowledgedMessageMap().remove(deliveryTag);
//sendtoDeadLetterQueue(AMQMessage message)
// message.queue = channel.getDefaultDeadLetterQueue();
// channel.requeue(deliveryTag);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
index 193c3a088b..621003be90 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
@@ -57,9 +57,6 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
{
AMQProtocolSession session = stateManager.getProtocolSession();
-
- //fixme Vhost not defined yet
- //session.getVirtualHost().getAuthenticationManager();
AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
SaslServer ss = session.getSaslServer();
@@ -72,11 +69,12 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
switch (authResult.status)
{
case ERROR:
- // Can't do this as we violate protocol. Need to send Close
- // throw new AMQException(AMQConstant.NOT_ALLOWED.getCode(), AMQConstant.NOT_ALLOWED.getName());
- _logger.info("Authentication failed");
- stateManager.changeState(AMQState.CONNECTION_CLOSING);
+ Exception cause = authResult.getCause();
+ _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+ // This should be abstracted
+ stateManager.changeState(AMQState.CONNECTION_CLOSING);
ConnectionCloseBody connectionCloseBody =
methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),
@@ -84,7 +82,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
body.getClazz(),
body.getMethod());
- session.writeFrame(connectionCloseBody.generateFrame(0) );
+ session.writeFrame(connectionCloseBody.generateFrame(0));
disposeSaslServer(session);
break;
case SUCCESS:
@@ -96,7 +94,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ConnectionStartOkMethodHandler.getConfiguredFrameSize(),
HeartbeatConfig.getInstance().getDelay());
session.writeFrame(tuneBody.generateFrame(0));
- session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
+ session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
disposeSaslServer(session);
break;
case CONTINUE:
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
index f02121c89f..f53e56601b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
@@ -93,7 +93,10 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
switch (authResult.status)
{
case ERROR:
- _logger.info("Authentication failed");
+ Exception cause = authResult.getCause();
+
+ _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
stateManager.changeState(AMQState.CONNECTION_CLOSING);
ConnectionCloseBody closeBody =
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java
index 491a2f80db..ccd42204d9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java
@@ -22,12 +22,10 @@ package org.apache.qpid.server.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.virtualhost.VirtualHost;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
index 97d25f650d..39b048aecb 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java
@@ -101,7 +101,7 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange
else if (!exchange.getType().equals(body.getType()))
{
- throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getType() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(), null);
+ throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getType() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
index 0f6dc7a19d..46182e8c00 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java
@@ -112,7 +112,7 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody>
if (!exch.isBound(routingKey, body.getArguments(), queue))
{
- queue.bind(routingKey, body.getArguments(), exch);
+ queue.bind(exch, routingKey, body.getArguments());
}
}
catch (AMQInvalidRoutingKeyException rke)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
index 7df864f189..447482ccf3 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
@@ -34,9 +34,10 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.security.access.Permission;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.store.MessageStore;
@@ -116,14 +117,14 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
queue = createQueue(queueName, body, virtualHost, session);
if (queue.isDurable() && !queue.isAutoDelete())
{
- store.createQueue(queue);
+ store.createQueue(queue, body.getArguments());
}
queueRegistry.registerQueue(queue);
if (autoRegister)
{
Exchange defaultExchange = exchangeRegistry.getDefaultExchange();
- queue.bind(queueName, null, defaultExchange);
+ queue.bind(defaultExchange, queueName, null);
_logger.info("Queue " + queueName + " bound to default exchange(" + defaultExchange.getName() + ")");
}
}
@@ -173,7 +174,9 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
{
final QueueRegistry registry = virtualHost.getQueueRegistry();
AMQShortString owner = body.getExclusive() ? session.getContextKey() : null;
- final AMQQueue queue = new AMQQueue(queueName, body.getDurable(), owner, body.getAutoDelete(), virtualHost);
+
+ final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, body.getDurable(), owner, body.getAutoDelete(), virtualHost,
+ body.getArguments());
if (body.getExclusive() && !body.getDurable())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
index 310a73ffeb..dfc36f5b93 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java
@@ -24,11 +24,10 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.QueueDeleteBody;
import org.apache.qpid.framing.QueueDeleteOkBody;
import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
import org.apache.qpid.server.store.MessageStore;
@@ -104,15 +103,16 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB
}
else
{
-
+
//Perform ACLs
virtualHost.getAccessManager().authorise(session, Permission.DELETE, body, queue);
- int purged = queue.delete(body.getIfUnused(), body.getIfEmpty());
+ int purged = queue.delete();
+
if (queue.isDurable())
{
- store.removeQueue(queue.getName());
+ store.removeQueue(queue);
}
MethodRegistry methodRegistry = session.getMethodRegistry();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
index a854c97f60..7377862875 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java
@@ -1,121 +1,119 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.QueuePurgeBody;
-import org.apache.qpid.framing.QueuePurgeOkBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQMethodEvent;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.access.Permission;
-
-public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
-{
- private static final QueuePurgeHandler _instance = new QueuePurgeHandler();
-
- public static QueuePurgeHandler getInstance()
- {
- return _instance;
- }
-
- private final boolean _failIfNotFound;
-
- public QueuePurgeHandler()
- {
- this(true);
- }
-
- public QueuePurgeHandler(boolean failIfNotFound)
- {
- _failIfNotFound = failIfNotFound;
- }
-
- public void methodReceived(AMQStateManager stateManager, QueuePurgeBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
- VirtualHost virtualHost = session.getVirtualHost();
- QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
-
- AMQChannel channel = session.getChannel(channelId);
-
-
- AMQQueue queue;
- if(body.getQueue() == null)
- {
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
-
- //get the default queue on the channel:
- queue = channel.getDefaultQueue();
-
- if(queue == null)
- {
- if(_failIfNotFound)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,"No queue specified.");
- }
- }
- }
- else
- {
- queue = queueRegistry.getQueue(body.getQueue());
- }
-
- if(queue == null)
- {
- if(_failIfNotFound)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.");
- }
- }
- else
- {
-
- //Perform ACLs
- virtualHost.getAccessManager().authorise(session, Permission.PURGE, body, queue);
-
- long purged = queue.clearQueue(channel.getStoreContext());
-
-
- if(!body.getNowait())
- {
-
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
- session.writeFrame(responseBody.generateFrame(channelId));
-
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.QueuePurgeBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.security.access.Permission;
+
+public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
+{
+ private static final QueuePurgeHandler _instance = new QueuePurgeHandler();
+
+ public static QueuePurgeHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private final boolean _failIfNotFound;
+
+ public QueuePurgeHandler()
+ {
+ this(true);
+ }
+
+ public QueuePurgeHandler(boolean failIfNotFound)
+ {
+ _failIfNotFound = failIfNotFound;
+ }
+
+ public void methodReceived(AMQStateManager stateManager, QueuePurgeBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+ VirtualHost virtualHost = session.getVirtualHost();
+ QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
+
+ AMQChannel channel = session.getChannel(channelId);
+
+
+ AMQQueue queue;
+ if(body.getQueue() == null)
+ {
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+
+ //get the default queue on the channel:
+ queue = channel.getDefaultQueue();
+
+ if(queue == null)
+ {
+ if(_failIfNotFound)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,"No queue specified.");
+ }
+ }
+ }
+ else
+ {
+ queue = queueRegistry.getQueue(body.getQueue());
+ }
+
+ if(queue == null)
+ {
+ if(_failIfNotFound)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.");
+ }
+ }
+ else
+ {
+
+ //Perform ACLs
+ virtualHost.getAccessManager().authorise(session, Permission.PURGE, body, queue);
+
+ long purged = queue.clearQueue(channel.getStoreContext());
+
+
+ if(!body.getNowait())
+ {
+
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
+ session.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
index 6b2924031a..d73e33d6c8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java
@@ -1,24 +1,3 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
package org.apache.qpid.server.handler;
import org.apache.log4j.Logger;
@@ -63,7 +42,7 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB
final AMQQueue queue;
- final AMQShortString routingKey;
+ final AMQShortString routingKey;
if (body.getQueue() == null)
{
@@ -105,7 +84,7 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB
try
{
- queue.unBind(routingKey, body.getArguments(), exch);
+ queue.unBind(exch, routingKey, body.getArguments());
}
catch (AMQInvalidRoutingKeyException rke)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java
index d24e4f6ffa..9475b83c8f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java
@@ -1,566 +1,566 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.AMQException;
-
-public class ServerMethodDispatcherImpl implements MethodDispatcher
-{
- private final AMQStateManager _stateManager;
-
- private static interface DispatcherFactory
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager);
- }
-
- private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
- new HashMap<ProtocolVersion, DispatcherFactory>();
-
-
- static
- {
- _dispatcherFactories.put(ProtocolVersion.v8_0,
- new DispatcherFactory()
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ServerMethodDispatcherImpl_8_0(stateManager);
- }
- });
-
- _dispatcherFactories.put(ProtocolVersion.v0_9,
- new DispatcherFactory()
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ServerMethodDispatcherImpl_0_9(stateManager);
- }
- });
-
- }
-
-
- private static final AccessRequestHandler _accessRequestHandler = AccessRequestHandler.getInstance();
- private static final ChannelCloseHandler _channelCloseHandler = ChannelCloseHandler.getInstance();
- private static final ChannelOpenHandler _channelOpenHandler = ChannelOpenHandler.getInstance();
- private static final ChannelCloseOkHandler _channelCloseOkHandler = ChannelCloseOkHandler.getInstance();
- private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
- private static final ConnectionCloseOkMethodHandler _connectionCloseOkMethodHandler = ConnectionCloseOkMethodHandler.getInstance();
- private static final ConnectionOpenMethodHandler _connectionOpenMethodHandler = ConnectionOpenMethodHandler.getInstance();
- private static final ConnectionTuneOkMethodHandler _connectionTuneOkMethodHandler = ConnectionTuneOkMethodHandler.getInstance();
- private static final ConnectionSecureOkMethodHandler _connectionSecureOkMethodHandler = ConnectionSecureOkMethodHandler.getInstance();
- private static final ConnectionStartOkMethodHandler _connectionStartOkMethodHandler = ConnectionStartOkMethodHandler.getInstance();
- private static final ExchangeDeclareHandler _exchangeDeclareHandler = ExchangeDeclareHandler.getInstance();
- private static final ExchangeDeleteHandler _exchangeDeleteHandler = ExchangeDeleteHandler.getInstance();
- private static final ExchangeBoundHandler _exchangeBoundHandler = ExchangeBoundHandler.getInstance();
- private static final BasicAckMethodHandler _basicAckMethodHandler = BasicAckMethodHandler.getInstance();
- private static final BasicRecoverMethodHandler _basicRecoverMethodHandler = BasicRecoverMethodHandler.getInstance();
- private static final BasicConsumeMethodHandler _basicConsumeMethodHandler = BasicConsumeMethodHandler.getInstance();
- private static final BasicGetMethodHandler _basicGetMethodHandler = BasicGetMethodHandler.getInstance();
- private static final BasicCancelMethodHandler _basicCancelMethodHandler = BasicCancelMethodHandler.getInstance();
- private static final BasicPublishMethodHandler _basicPublishMethodHandler = BasicPublishMethodHandler.getInstance();
- private static final BasicQosHandler _basicQosHandler = BasicQosHandler.getInstance();
- private static final QueueBindHandler _queueBindHandler = QueueBindHandler.getInstance();
- private static final QueueDeclareHandler _queueDeclareHandler = QueueDeclareHandler.getInstance();
- private static final QueueDeleteHandler _queueDeleteHandler = QueueDeleteHandler.getInstance();
- private static final QueuePurgeHandler _queuePurgeHandler = QueuePurgeHandler.getInstance();
- private static final ChannelFlowHandler _channelFlowHandler = ChannelFlowHandler.getInstance();
- private static final TxSelectHandler _txSelectHandler = TxSelectHandler.getInstance();
- private static final TxCommitHandler _txCommitHandler = TxCommitHandler.getInstance();
- private static final TxRollbackHandler _txRollbackHandler = TxRollbackHandler.getInstance();
- private static final BasicRejectMethodHandler _basicRejectMethodHandler = BasicRejectMethodHandler.getInstance();
-
-
-
- public static MethodDispatcher createMethodDispatcher(AMQStateManager stateManager, ProtocolVersion protocolVersion)
- {
- return _dispatcherFactories.get(protocolVersion).createMethodDispatcher(stateManager);
- }
-
-
- public ServerMethodDispatcherImpl(AMQStateManager stateManager)
- {
- _stateManager = stateManager;
- }
-
-
- protected AMQStateManager getStateManager()
- {
- return _stateManager;
- }
-
-
-
- public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
- {
- _accessRequestHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
- {
- _basicAckMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
- {
- _basicCancelMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
- {
- _basicConsumeMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
- {
- _basicGetMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
- {
- _basicPublishMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
- {
- _basicQosHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
- {
- _basicRecoverMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
- {
- _basicRejectMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
- {
- _channelOpenHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
- {
- _channelCloseHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
- {
- _channelCloseOkHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
- {
- _channelFlowHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
- {
- _connectionOpenMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
- {
- _connectionCloseMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
- {
- _connectionCloseOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
- {
- _connectionSecureOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
- {
- _connectionStartOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
- {
- _connectionTuneOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
- {
- _exchangeBoundHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
- {
- _exchangeDeclareHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
- {
- _exchangeDeleteHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
- {
- _queueBindHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
- {
- _queueDeclareHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
- {
- _queueDeleteHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
- {
- _queuePurgeHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
- {
- _txCommitHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
- {
- _txRollbackHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
- {
- _txSelectHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.AMQException;
+
+public class ServerMethodDispatcherImpl implements MethodDispatcher
+{
+ private final AMQStateManager _stateManager;
+
+ private static interface DispatcherFactory
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager);
+ }
+
+ private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
+ new HashMap<ProtocolVersion, DispatcherFactory>();
+
+
+ static
+ {
+ _dispatcherFactories.put(ProtocolVersion.v8_0,
+ new DispatcherFactory()
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ServerMethodDispatcherImpl_8_0(stateManager);
+ }
+ });
+
+ _dispatcherFactories.put(ProtocolVersion.v0_9,
+ new DispatcherFactory()
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ServerMethodDispatcherImpl_0_9(stateManager);
+ }
+ });
+
+ }
+
+
+ private static final AccessRequestHandler _accessRequestHandler = AccessRequestHandler.getInstance();
+ private static final ChannelCloseHandler _channelCloseHandler = ChannelCloseHandler.getInstance();
+ private static final ChannelOpenHandler _channelOpenHandler = ChannelOpenHandler.getInstance();
+ private static final ChannelCloseOkHandler _channelCloseOkHandler = ChannelCloseOkHandler.getInstance();
+ private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
+ private static final ConnectionCloseOkMethodHandler _connectionCloseOkMethodHandler = ConnectionCloseOkMethodHandler.getInstance();
+ private static final ConnectionOpenMethodHandler _connectionOpenMethodHandler = ConnectionOpenMethodHandler.getInstance();
+ private static final ConnectionTuneOkMethodHandler _connectionTuneOkMethodHandler = ConnectionTuneOkMethodHandler.getInstance();
+ private static final ConnectionSecureOkMethodHandler _connectionSecureOkMethodHandler = ConnectionSecureOkMethodHandler.getInstance();
+ private static final ConnectionStartOkMethodHandler _connectionStartOkMethodHandler = ConnectionStartOkMethodHandler.getInstance();
+ private static final ExchangeDeclareHandler _exchangeDeclareHandler = ExchangeDeclareHandler.getInstance();
+ private static final ExchangeDeleteHandler _exchangeDeleteHandler = ExchangeDeleteHandler.getInstance();
+ private static final ExchangeBoundHandler _exchangeBoundHandler = ExchangeBoundHandler.getInstance();
+ private static final BasicAckMethodHandler _basicAckMethodHandler = BasicAckMethodHandler.getInstance();
+ private static final BasicRecoverMethodHandler _basicRecoverMethodHandler = BasicRecoverMethodHandler.getInstance();
+ private static final BasicConsumeMethodHandler _basicConsumeMethodHandler = BasicConsumeMethodHandler.getInstance();
+ private static final BasicGetMethodHandler _basicGetMethodHandler = BasicGetMethodHandler.getInstance();
+ private static final BasicCancelMethodHandler _basicCancelMethodHandler = BasicCancelMethodHandler.getInstance();
+ private static final BasicPublishMethodHandler _basicPublishMethodHandler = BasicPublishMethodHandler.getInstance();
+ private static final BasicQosHandler _basicQosHandler = BasicQosHandler.getInstance();
+ private static final QueueBindHandler _queueBindHandler = QueueBindHandler.getInstance();
+ private static final QueueDeclareHandler _queueDeclareHandler = QueueDeclareHandler.getInstance();
+ private static final QueueDeleteHandler _queueDeleteHandler = QueueDeleteHandler.getInstance();
+ private static final QueuePurgeHandler _queuePurgeHandler = QueuePurgeHandler.getInstance();
+ private static final ChannelFlowHandler _channelFlowHandler = ChannelFlowHandler.getInstance();
+ private static final TxSelectHandler _txSelectHandler = TxSelectHandler.getInstance();
+ private static final TxCommitHandler _txCommitHandler = TxCommitHandler.getInstance();
+ private static final TxRollbackHandler _txRollbackHandler = TxRollbackHandler.getInstance();
+ private static final BasicRejectMethodHandler _basicRejectMethodHandler = BasicRejectMethodHandler.getInstance();
+
+
+
+ public static MethodDispatcher createMethodDispatcher(AMQStateManager stateManager, ProtocolVersion protocolVersion)
+ {
+ return _dispatcherFactories.get(protocolVersion).createMethodDispatcher(stateManager);
+ }
+
+
+ public ServerMethodDispatcherImpl(AMQStateManager stateManager)
+ {
+ _stateManager = stateManager;
+ }
+
+
+ protected AMQStateManager getStateManager()
+ {
+ return _stateManager;
+ }
+
+
+
+ public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
+ {
+ _accessRequestHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
+ {
+ _basicAckMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
+ {
+ _basicCancelMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
+ {
+ _basicConsumeMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
+ {
+ _basicGetMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
+ {
+ _basicPublishMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
+ {
+ _basicQosHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
+ {
+ _basicRecoverMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
+ {
+ _basicRejectMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
+ {
+ _channelOpenHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
+ {
+ _channelCloseHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
+ {
+ _channelCloseOkHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
+ {
+ _channelFlowHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
+ {
+ _connectionOpenMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
+ {
+ _connectionCloseMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
+ {
+ _connectionCloseOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
+ {
+ _connectionSecureOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
+ {
+ _connectionStartOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
+ {
+ _connectionTuneOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
+ {
+ _exchangeBoundHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
+ {
+ _exchangeDeclareHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
+ {
+ _exchangeDeleteHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
+ {
+ _queueBindHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
+ {
+ _queueDeclareHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
+ {
+ _queueDeleteHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
+ {
+ _queuePurgeHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
+ {
+ _txCommitHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
+ {
+ _txRollbackHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
+ {
+ _txSelectHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java
index 382a85347b..8b1dca77ba 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java
@@ -1,164 +1,164 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-
-import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.AMQException;
-
-
-
-public class ServerMethodDispatcherImpl_0_9
- extends ServerMethodDispatcherImpl
- implements MethodDispatcher_0_9
-
-{
-
- private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler =
- BasicRecoverSyncMethodHandler.getInstance();
- private static final QueueUnbindHandler _queueUnbindHandler =
- QueueUnbindHandler.getInstance();
-
-
- public ServerMethodDispatcherImpl_0_9(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
- public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- _basicRecoverSyncMethodHandler.methodReceived(getStateManager(), body, channelId);
- return true;
- }
-
- public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelOk(ChannelOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelPing(ChannelPingBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelPong(ChannelPongBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelResume(ChannelResumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageCheckpoint(MessageCheckpointBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageClose(MessageCloseBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageConsume(MessageConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOffset(MessageOffsetBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOk(MessageOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOpen(MessageOpenBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageQos(MessageQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageReject(MessageRejectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageResume(MessageResumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageTransfer(MessageTransferBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
- {
- _queueUnbindHandler.methodReceived(getStateManager(),body,channelId);
- return true;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+
+import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.AMQException;
+
+
+
+public class ServerMethodDispatcherImpl_0_9
+ extends ServerMethodDispatcherImpl
+ implements MethodDispatcher_0_9
+
+{
+
+ private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler =
+ BasicRecoverSyncMethodHandler.getInstance();
+ private static final QueueUnbindHandler _queueUnbindHandler =
+ QueueUnbindHandler.getInstance();
+
+
+ public ServerMethodDispatcherImpl_0_9(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+ public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ _basicRecoverSyncMethodHandler.methodReceived(getStateManager(), body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelOk(ChannelOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelPing(ChannelPingBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelPong(ChannelPongBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelResume(ChannelResumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageCheckpoint(MessageCheckpointBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageClose(MessageCloseBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageConsume(MessageConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOffset(MessageOffsetBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOk(MessageOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOpen(MessageOpenBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageQos(MessageQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageReject(MessageRejectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageResume(MessageResumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageTransfer(MessageTransferBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
+ {
+ _queueUnbindHandler.methodReceived(getStateManager(),body,channelId);
+ return true;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java
index 22f64cf7d3..d599ca3d4e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java
@@ -1,86 +1,86 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.AMQException;
-
-public class ServerMethodDispatcherImpl_8_0
- extends ServerMethodDispatcherImpl
- implements MethodDispatcher_8_0
-{
- public ServerMethodDispatcherImpl_8_0(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
- public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTestContent(TestContentBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestContentOk(TestContentOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestInteger(TestIntegerBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestIntegerOk(TestIntegerOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestString(TestStringBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestStringOk(TestStringOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTable(TestTableBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTableOk(TestTableOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.AMQException;
+
+public class ServerMethodDispatcherImpl_8_0
+ extends ServerMethodDispatcherImpl
+ implements MethodDispatcher_8_0
+{
+ public ServerMethodDispatcherImpl_8_0(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+ public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTestContent(TestContentBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestContentOk(TestContentOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestInteger(TestIntegerBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestIntegerOk(TestIntegerOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestString(TestStringBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestStringOk(TestStringOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestTable(TestTableBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestTableOk(TestTableOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
index 79cc722e0e..9b23d88838 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java
@@ -23,10 +23,8 @@ package org.apache.qpid.server.handler;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.TxCommitBody;
-import org.apache.qpid.framing.TxCommitOkBody;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.state.AMQStateManager;
@@ -70,7 +68,7 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody>
AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
session.writeFrame(responseBody.generateFrame(channelId));
- channel.processReturns(session);
+ channel.processReturns();
}
catch (AMQException e)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java b/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java
index 0abb3cdd7d..fb18519fe1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java
@@ -1,33 +1,33 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.AMQException;
-
-public class UnexpectedMethodException extends AMQException
-{
- public UnexpectedMethodException(AMQMethodBody body)
- {
- super("Unexpected method recevied: " + body.getClass().getName());
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.AMQException;
+
+public class UnexpectedMethodException extends AMQException
+{
+ public UnexpectedMethodException(AMQMethodBody body)
+ {
+ super("Unexpected method recevied: " + body.getClass().getName());
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
index 576d577b40..e01c5aabbf 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java
@@ -1,57 +1,57 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output;
-
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.AMQDataBlock;
-import org.apache.qpid.AMQException;
-
-public interface ProtocolOutputConverter
-{
- void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag);
-
- interface Factory
- {
- ProtocolOutputConverter newInstance(AMQProtocolSession session);
- }
-
- void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException;
-
- void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
-
- byte getProtocolMinorVersion();
-
- byte getProtocolMajorVersion();
-
- void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException;
-
- void writeFrame(AMQDataBlock block);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output;
+
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.AMQException;
+
+public interface ProtocolOutputConverter
+{
+ void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag);
+
+ interface Factory
+ {
+ ProtocolOutputConverter newInstance(AMQProtocolSession session);
+ }
+
+ void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException;
+
+ void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
+
+ byte getProtocolMinorVersion();
+
+ byte getProtocolMajorVersion();
+
+ void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException;
+
+ void writeFrame(AMQDataBlock block);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java
index 02fb1429c0..36e7e88fd6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java
@@ -1,61 +1,61 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output;
-
-import org.apache.qpid.server.output.ProtocolOutputConverter.Factory;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.framing.ProtocolVersion;
-
-import java.util.Map;
-import java.util.HashMap;
-
-public class ProtocolOutputConverterRegistry
-{
-
- private static final Map<ProtocolVersion, Factory> _registry =
- new HashMap<ProtocolVersion, Factory>();
-
-
- static
- {
- register(ProtocolVersion.v8_0, org.apache.qpid.server.output.amqp0_8.ProtocolOutputConverterImpl.getInstanceFactory());
- register(ProtocolVersion.v0_9, org.apache.qpid.server.output.amqp0_9.ProtocolOutputConverterImpl.getInstanceFactory());
-
- }
-
- private static void register(ProtocolVersion version, Factory converter)
- {
-
- _registry.put(version,converter);
- }
-
-
- public static ProtocolOutputConverter getConverter(AMQProtocolSession session)
- {
- return _registry.get(session.getProtocolVersion()).newInstance(session);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output;
+
+import org.apache.qpid.server.output.ProtocolOutputConverter.Factory;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.framing.ProtocolVersion;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class ProtocolOutputConverterRegistry
+{
+
+ private static final Map<ProtocolVersion, Factory> _registry =
+ new HashMap<ProtocolVersion, Factory>();
+
+
+ static
+ {
+ register(ProtocolVersion.v8_0, org.apache.qpid.server.output.amqp0_8.ProtocolOutputConverterImpl.getInstanceFactory());
+ register(ProtocolVersion.v0_9, org.apache.qpid.server.output.amqp0_9.ProtocolOutputConverterImpl.getInstanceFactory());
+
+ }
+
+ private static void register(ProtocolVersion version, Factory converter)
+ {
+
+ _registry.put(version,converter);
+ }
+
+
+ public static ProtocolOutputConverter getConverter(AMQProtocolSession session)
+ {
+ return _registry.get(session.getProtocolVersion()).newInstance(session);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
index d4cb7c878f..2b55d294b5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
@@ -1,285 +1,284 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output.amqp0_8;
-
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.AMQException;
-
-import org.apache.mina.common.ByteBuffer;
-
-import java.util.Iterator;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
-
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final Long messageId = message.getMessageId();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
-
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
-
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext,messageId, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final long messageId = message.getMessageId();
-
- AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
-
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, messageId, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicDeliverBody deliverBody =
- methodRegistry.createBasicDeliverBody(consumerTag,
- deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey());
- AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
-
-
- return deliverFrame;
- }
-
- private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicGetOkBody getOkBody =
- methodRegistry.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
- queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
-
- return getOkFrame;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
- {
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicReturnBody basicReturnBody =
- methodRegistry.createBasicReturnBody(replyCode,
- replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
-
- return returnFrame;
- }
-
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output.amqp0_8;
+
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.AMQException;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.util.Iterator;
+
+public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
+{
+
+
+ public static Factory getInstanceFactory()
+ {
+ return new Factory()
+ {
+
+ public ProtocolOutputConverter newInstance(AMQProtocolSession session)
+ {
+ return new ProtocolOutputConverterImpl(session);
+ }
+ };
+ }
+
+ private final AMQProtocolSession _protocolSession;
+
+ private ProtocolOutputConverterImpl(AMQProtocolSession session)
+ {
+ _protocolSession = session;
+ }
+
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _protocolSession;
+ }
+
+ public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext);
+
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, i);
+ writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+
+ AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext);
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, i);
+ writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicDeliverBody deliverBody =
+ methodRegistry.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey());
+ AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
+
+
+ return deliverFrame;
+ }
+
+ private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicGetOkBody getOkBody =
+ methodRegistry.createBasicGetOkBody(deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey(),
+ queueSize);
+ AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
+
+ return getOkFrame;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return getProtocolSession().getProtocolMinorVersion();
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return getProtocolSession().getProtocolMajorVersion();
+ }
+
+ private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ {
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicReturnBody basicReturnBody =
+ methodRegistry.createBasicReturnBody(replyCode,
+ replyText,
+ message.getMessagePublishInfo().getExchange(),
+ message.getMessagePublishInfo().getRoutingKey());
+ AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+
+ return returnFrame;
+ }
+
+ public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException
+ {
+ AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ if (bodyFrameIterator.hasNext())
+ {
+ AMQDataBlock firstContentBody = bodyFrameIterator.next();
+ AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
+
+ writeFrame(compositeBlock);
+ }
+
+ //
+ // Now start writing out the other content bodies
+ // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
+ //
+ while (bodyFrameIterator.hasNext())
+ {
+ writeFrame(bodyFrameIterator.next());
+ }
+ }
+
+
+ public void writeFrame(AMQDataBlock block)
+ {
+ getProtocolSession().writeFrame(block);
+ }
+
+
+ public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
+ {
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
+ writeFrame(basicCancelOkBody.generateFrame(channelId));
+
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
index f87d3bcae1..c76c262edd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
@@ -1,397 +1,370 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.output.amqp0_9;
-
-import org.apache.mina.common.ByteBuffer;
-
-import java.util.Iterator;
-
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
- private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
-
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
-
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final Long messageId = message.getMessageId();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
-
- if(bodyCount == 0)
- {
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
-
- CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext,messageId, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
- }
-
-
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final long messageId = message.getMessageId();
-
- AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
-
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, messageId, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
- throws AMQException
- {
-
-
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
-
- final AMQBody returnBlock = new AMQBody()
- {
-
-
-
- private final boolean _isRedelivered = messageHandle.isRedelivered();
- private final AMQShortString _exchangeName = pb.getExchange();
- private final AMQShortString _routingKey = pb.getRoutingKey();
-
-
- public AMQBody _underlyingBody;
-
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- _isRedelivered,
- _exchangeName,
- _routingKey);
-
-
-
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
- }
-
- private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
-
- BasicGetOkBody getOkBody =
- METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
- queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
-
- return getOkFrame;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
- {
-
- BasicReturnBody basicReturnBody =
- METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
-
- return returnFrame;
- }
-
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
-
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
-
- BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
-
-}
+package org.apache.qpid.server.output.amqp0_9;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.util.Iterator;
+
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+
+public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
+{
+ private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
+ private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
+
+
+ public static Factory getInstanceFactory()
+ {
+ return new Factory()
+ {
+
+ public ProtocolOutputConverter newInstance(AMQProtocolSession session)
+ {
+ return new ProtocolOutputConverterImpl(session);
+ }
+ };
+ }
+
+ private final AMQProtocolSession _protocolSession;
+
+ private ProtocolOutputConverterImpl(AMQProtocolSession session)
+ {
+ _protocolSession = session;
+ }
+
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _protocolSession;
+ }
+
+ public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
+
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext);
+
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
+ contentHeaderBody);
+
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+
+ AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
+
+ CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, i);
+ writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
+ }
+
+
+ }
+
+ }
+
+ private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
+ {
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ contentHeaderBody);
+ return contentHeader;
+ }
+
+
+ public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+
+ AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+
+
+ AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext);
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, i);
+ writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+
+ final boolean isRedelivered = messageHandle.isRedelivered();
+ final AMQShortString exchangeName = pb.getExchange();
+ final AMQShortString routingKey = pb.getRoutingKey();
+
+ final AMQBody returnBlock = new AMQBody()
+ {
+
+ public AMQBody _underlyingBody;
+
+ public AMQBody createAMQBody()
+ {
+ return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ isRedelivered,
+ exchangeName,
+ routingKey);
+
+
+
+
+
+ }
+
+ public byte getFrameType()
+ {
+ return AMQMethodBody.TYPE;
+ }
+
+ public int getSize()
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ return _underlyingBody.getSize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ _underlyingBody.writePayload(buffer);
+ }
+
+ public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
+ throws AMQException
+ {
+ throw new AMQException("This block should never be dispatched!");
+ }
+ };
+ return returnBlock;
+ }
+
+ private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+
+ BasicGetOkBody getOkBody =
+ METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey(),
+ queueSize);
+ AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
+
+ return getOkFrame;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return getProtocolSession().getProtocolMinorVersion();
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return getProtocolSession().getProtocolMajorVersion();
+ }
+
+ private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ {
+
+ BasicReturnBody basicReturnBody =
+ METHOD_REGISTRY.createBasicReturnBody(replyCode,
+ replyText,
+ message.getMessagePublishInfo().getExchange(),
+ message.getMessagePublishInfo().getRoutingKey());
+ AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+
+ return returnFrame;
+ }
+
+ public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException
+ {
+ AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
+
+ AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+
+ Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ if (bodyFrameIterator.hasNext())
+ {
+ AMQDataBlock firstContentBody = bodyFrameIterator.next();
+ AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
+
+ writeFrame(compositeBlock);
+ }
+
+ //
+ // Now start writing out the other content bodies
+ // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
+ //
+ while (bodyFrameIterator.hasNext())
+ {
+ writeFrame(bodyFrameIterator.next());
+ }
+ }
+
+
+ public void writeFrame(AMQDataBlock block)
+ {
+ getProtocolSession().writeFrame(block);
+ }
+
+
+ public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
+ {
+
+ BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
+ writeFrame(basicCancelOkBody.generateFrame(channelId));
+
+ }
+
+
+ public static final class CompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final AMQBody _contentBody;
+ private final int _channel;
+
+
+ public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+ _contentBody = contentBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
+ }
+ }
+
+ public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final int _channel;
+
+
+ public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
index 4267642b14..64914b407d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
@@ -25,6 +25,7 @@ import org.apache.log4j.Logger;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.common.IoSession;
+import org.apache.mina.common.CloseFuture;
import org.apache.mina.transport.vmpipe.VmPipeAddress;
import org.apache.qpid.AMQChannelException;
@@ -49,6 +50,7 @@ import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.transport.Sender;
import javax.management.JMException;
import javax.security.sasl.SaslServer;
@@ -99,7 +101,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
private Object _lastSent;
- private boolean _closed;
+ protected boolean _closed;
// maximum number of channels this session should have
private long _maxNoOfChannels = 1000;
@@ -113,6 +115,10 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
private ProtocolOutputConverter _protocolOutputConverter;
private Principal _authorizedID;
private MethodDispatcher _dispatcher;
+ private ProtocolSessionIdentifier _sessionIdentifier;
+
+ private static final long LAST_WRITE_FUTURE_JOIN_TIMEOUT = 60000L;
+ private org.apache.mina.common.WriteFuture _lastWriteFuture;
public ManagedObject getManagedObject()
{
@@ -120,7 +126,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
}
public AMQMinaProtocolSession(IoSession session, VirtualHostRegistry virtualHostRegistry, AMQCodecFactory codecFactory)
- throws AMQException
+ throws AMQException
{
_stateManager = new AMQStateManager(virtualHostRegistry, this);
_minaProtocolSession = session;
@@ -144,7 +150,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
}
public AMQMinaProtocolSession(IoSession session, VirtualHostRegistry virtualHostRegistry, AMQCodecFactory codecFactory,
- AMQStateManager stateManager) throws AMQException
+ AMQStateManager stateManager) throws AMQException
{
_stateManager = stateManager;
_minaProtocolSession = session;
@@ -221,15 +227,14 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
{
if (_logger.isInfoEnabled())
{
- _logger.info("Channel[" + channelId + "] awaiting closure ignoring");
+ _logger.info("Channel[" + channelId + "] awaiting closure. Should close socket as client did not close-ok :" + frame);
}
+ closeProtocolSession();
return;
}
}
-
-
try
{
body.handle(channelId, this);
@@ -257,7 +262,6 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
String locales = "en_US";
-
AMQMethodBody responseBody = getMethodRegistry().createConnectionStartBody((short) getProtocolMajorVersion(),
(short) getProtocolMinorVersion(),
null,
@@ -265,7 +269,6 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
locales.getBytes());
_minaProtocolSession.write(responseBody.generateFrame(0));
-
}
catch (AMQException e)
{
@@ -331,27 +334,16 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
_logger.info("Closing connection due to: " + e.getMessage());
}
- closeSession();
-
AMQConnectionException ce =
- evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR,
- AMQConstant.CHANNEL_ERROR.getName().toString());
+ evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR,
+ AMQConstant.CHANNEL_ERROR.getName().toString());
- _stateManager.changeState(AMQState.CONNECTION_CLOSING);
- writeFrame(ce.getCloseFrame(channelId));
+ closeConnection(channelId, ce, false);
}
}
catch (AMQConnectionException e)
{
- if (_logger.isInfoEnabled())
- {
- _logger.info("Closing connection due to: " + e.getMessage());
- }
-
- markChannelAwaitingCloseOk(channelId);
- closeSession();
- _stateManager.changeState(AMQState.CONNECTION_CLOSING);
- writeFrame(e.getCloseFrame(channelId));
+ closeConnection(channelId, e, false);
}
}
catch (Exception e)
@@ -364,7 +356,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
_logger.error("Unexpected exception while processing frame. Closing connection.", e);
- _minaProtocolSession.close();
+ closeProtocolSession();
}
}
@@ -373,7 +365,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
AMQChannel channel = getAndAssertChannel(channelId);
- channel.publishContentHeader(body, this);
+ channel.publishContentHeader(body);
}
@@ -381,7 +373,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
{
AMQChannel channel = getAndAssertChannel(channelId);
- channel.publishContentBody(body, this);
+ channel.publishContentBody(body);
}
public void heartbeatBodyReceived(int channelId, HeartbeatBody body)
@@ -398,7 +390,8 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
public void writeFrame(AMQDataBlock frame)
{
_lastSent = frame;
- _minaProtocolSession.write(frame);
+
+ _lastWriteFuture = _minaProtocolSession.write(frame);
}
public AMQShortString getContextKey()
@@ -430,7 +423,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
public AMQChannel getChannel(int channelId) throws AMQException
{
final AMQChannel channel =
- ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId);
+ ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId);
if ((channel == null) || channel.isClosing())
{
return null;
@@ -443,7 +436,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
public boolean channelAwaitingClosure(int channelId)
{
- return _closingChannelsList.contains(channelId);
+ return !_closingChannelsList.isEmpty() && _closingChannelsList.contains(channelId);
}
public void addChannel(AMQChannel channel) throws AMQException
@@ -463,8 +456,8 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
if (_channelMap.size() == _maxNoOfChannels)
{
String errorMessage =
- toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels
- + "); can't create channel";
+ toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels
+ + "); can't create channel";
_logger.error(errorMessage);
throw new AMQException(AMQConstant.NOT_ALLOWED, errorMessage);
}
@@ -536,7 +529,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
{
try
{
- channel.close(this);
+ channel.close();
markChannelAwaitingCloseOk(channelId);
}
finally
@@ -602,7 +595,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
{
for (AMQChannel channel : _channelMap.values())
{
- channel.close(this);
+ channel.close();
}
_channelMap.clear();
@@ -618,6 +611,12 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
if (!_closed)
{
_closed = true;
+
+ if (_virtualHost != null)
+ {
+ _virtualHost.getConnectionRegistry().deregisterConnection(this);
+ }
+
closeAllChannels();
if (_managedObject != null)
{
@@ -631,9 +630,54 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
}
}
+ public void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Closing connection due to: " + e.getMessage());
+ }
+
+ markChannelAwaitingCloseOk(channelId);
+ closeSession();
+ _stateManager.changeState(AMQState.CONNECTION_CLOSING);
+ writeFrame(e.getCloseFrame(channelId));
+
+ if (closeProtocolSession)
+ {
+ closeProtocolSession();
+ }
+ }
+
+ public void closeProtocolSession()
+ {
+ closeProtocolSession(true);
+ }
+
+ public void closeProtocolSession(boolean waitLast)
+ {
+ _logger.debug("Waiting for last write to join.");
+ if (waitLast && (_lastWriteFuture != null))
+ {
+ _lastWriteFuture.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT);
+ }
+
+ _logger.debug("REALLY Closing protocol session:" + _minaProtocolSession);
+ final CloseFuture future = _minaProtocolSession.close();
+ future.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT);
+
+ try
+ {
+ _stateManager.changeState(AMQState.CONNECTION_CLOSED);
+ }
+ catch (AMQException e)
+ {
+ _logger.info(e.getMessage());
+ }
+ }
+
public String toString()
{
- return "AMQProtocolSession(" + _minaProtocolSession.getRemoteAddress() + ")";
+ return _minaProtocolSession.getRemoteAddress() + "(" + (getAuthorizedID() == null ? "?" : getAuthorizedID().getName() + ")");
}
public String dump()
@@ -702,6 +746,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
_clientVersion = new AMQShortString(_clientProperties.getString(ClientProperties.version.toString()));
}
}
+ _sessionIdentifier = new ProtocolSessionIdentifier(this);
}
private void setProtocolVersion(ProtocolVersion pv)
@@ -739,7 +784,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
public Object getClientIdentifier()
{
- return _minaProtocolSession.getRemoteAddress();
+ return (_minaProtocolSession != null) ? _minaProtocolSession.getRemoteAddress() : null;
}
public VirtualHost getVirtualHost()
@@ -750,6 +795,9 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
public void setVirtualHost(VirtualHost virtualHost) throws AMQException
{
_virtualHost = virtualHost;
+
+ _virtualHost.getConnectionRegistry().registerConnection(this);
+
_managedObject = createMBean();
_managedObject.register();
}
@@ -789,8 +837,23 @@ public class AMQMinaProtocolSession implements AMQProtocolSession, Managable
return _dispatcher;
}
+ public ProtocolSessionIdentifier getSessionIdentifier()
+ {
+ return _sessionIdentifier;
+ }
+
public String getClientVersion()
{
return (_clientVersion == null) ? null : _clientVersion.toString();
}
+
+ public void setSender(Sender<java.nio.ByteBuffer> sender)
+ {
+ // No-op, interface munging between this and AMQProtocolSession
+ }
+
+ public void init()
+ {
+ // No-op, interface munging between this and AMQProtocolSession
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java
index 92f951ce39..a7599a3e0d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java
@@ -1,46 +1,46 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
-
-/**
- * AMQNoMethodHandlerException represents the case where no method handler exists to handle an AQMP method.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represents failure to handle an AMQP method.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Missing method handler. Unlikely to ever happen, and if it does its a coding error. Consider replacing with a
- * Runtime.
- */
-public class AMQNoMethodHandlerException extends AMQException
-{
- public AMQNoMethodHandlerException(AMQMethodEvent<AMQMethodBody> evt)
- {
- super("AMQMethodEvent " + evt + " was not processed by any listener on Broker.");
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQMethodEvent;
+
+/**
+ * AMQNoMethodHandlerException represents the case where no method handler exists to handle an AQMP method.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents failure to handle an AMQP method.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Missing method handler. Unlikely to ever happen, and if it does its a coding error. Consider replacing with a
+ * Runtime.
+ */
+public class AMQNoMethodHandlerException extends AMQException
+{
+ public AMQNoMethodHandlerException(AMQMethodEvent<AMQMethodBody> evt)
+ {
+ super("AMQMethodEvent " + evt + " was not processed by any listener on Broker.");
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java
index ad1c507c04..d8dbf97e49 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQPFastProtocolHandler.java
@@ -265,6 +265,10 @@ public class AMQPFastProtocolHandler extends IoHandlerAdapter
*/
public void messageSent(IoSession protocolSession, Object object) throws Exception
{
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Message sent: " + object);
+ }
}
protected boolean isSSLClient(ConnectorConfiguration connectionConfig,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
index c9316f7405..1bac601225 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
@@ -23,7 +23,9 @@ package org.apache.qpid.server.protocol;
import javax.security.sasl.SaslServer;
import org.apache.qpid.AMQException;
+import org.apache.qpid.common.ClientProperties;
import org.apache.qpid.framing.*;
+import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.output.ProtocolOutputConverter;
@@ -35,7 +37,27 @@ import java.security.Principal;
public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
{
-
+ public static final class ProtocolSessionIdentifier
+ {
+ private final Object _sessionIdentifier;
+ private final Object _sessionInstance;
+
+ ProtocolSessionIdentifier(AMQProtocolSession session)
+ {
+ _sessionIdentifier = session.getClientIdentifier();
+ _sessionInstance = session.getClientProperties() == null ? null : session.getClientProperties().getObject(ClientProperties.instance.toAMQShortString());
+ }
+
+ public Object getSessionIdentifier()
+ {
+ return _sessionIdentifier;
+ }
+
+ public Object getSessionInstance()
+ {
+ return _sessionInstance;
+ }
+ }
public static interface Task
{
@@ -129,6 +151,10 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
/** This must be called when the session is _closed in order to free up any resources managed by the session. */
void closeSession() throws AMQException;
+ /** This must be called to close the session in order to free up any resources managed by the session. */
+ void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException;
+
+
/** @return a key that uniquely identifies this session */
Object getKey();
@@ -175,5 +201,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
public MethodRegistry getMethodRegistry();
public MethodDispatcher getMethodDispatcher();
+
+ public ProtocolSessionIdentifier getSessionIdentifier();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
index bb2db8d506..6e72aa062f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
@@ -1,46 +1,46 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQDataBlock;
-
-/**
- * UnknnownMessageTypeException represents a failure when Mina passes an unexpected frame type.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represents failure to cast a frame to its expected type.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Seems like this exception was created to handle an unsafe type cast that will never happen in practice. Would
- * be better just to leave that as a ClassCastException. However, check the framing layer catches this error
- * first.
- */
-public class UnknnownMessageTypeException extends AMQException
-{
- public UnknnownMessageTypeException(AMQDataBlock message)
- {
- super("Unknown message type: " + message.getClass().getName() + ": " + message);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQDataBlock;
+
+/**
+ * UnknnownMessageTypeException represents a failure when Mina passes an unexpected frame type.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents failure to cast a frame to its expected type.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Seems like this exception was created to handle an unsafe type cast that will never happen in practice. Would
+ * be better just to leave that as a ClassCastException. However, check the framing layer catches this error
+ * first.
+ */
+public class UnknnownMessageTypeException extends AMQException
+{
+ public UnknnownMessageTypeException(AMQDataBlock message)
+ {
+ super("Unknown message type: " + message.getClass().getName() + ": " + message);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
index a76b13ce74..a485649410 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
@@ -25,131 +25,55 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQBody;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.txn.TransactionalContext;
-import org.apache.qpid.server.exchange.Exchange;
-import java.util.HashMap;
-import java.util.HashSet;
+
import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A deliverable message.
*/
-public class AMQMessage
+public class AMQMessage implements Filterable<AMQException>
{
/** Used for debugging purposes. */
private static final Logger _log = Logger.getLogger(AMQMessage.class);
- /** Used in clustering. @todo What for? */
- private Set<Object> _tokens;
-
- /** Only use in clustering. @todo What for? */
- private AMQProtocolSession _publisher;
-
- private final Long _messageId;
-
private final AtomicInteger _referenceCount = new AtomicInteger(1);
- private AMQMessageHandle _messageHandle;
+ private final AMQMessageHandle _messageHandle;
/** Holds the transactional context in which this message is being processed. */
- private TransactionalContext _txnContext;
+ private StoreContext _storeContext;
+
+ /** Flag to indicate that this message requires 'immediate' delivery. */
+
+ private static final byte IMMEDIATE = 0x01;
/**
* Flag to indicate whether this message has been delivered to a consumer. Used in implementing return functionality
* for messages published with the 'immediate' flag.
*/
- private boolean _deliveredToConsumer;
- /** Flag to indicate that this message requires 'immediate' delivery. */
- private boolean _immediate;
+ private static final byte DELIVERED_TO_CONSUMER = 0x02;
- private TransientMessageData _transientMessageData = new TransientMessageData();
+ private byte _flags = 0;
private long _expiration;
+ private final long _size;
+ private AMQProtocolSession.ProtocolSessionIdentifier _sessionIdentifier;
+ private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER);
- private Exchange _exchange;
- private static final boolean SYNCED_CLOCKS =
- ApplicationRegistry.getInstance().getConfiguration().getBoolean("advanced.synced-clocks", false);
-
- private static final long UNKNOWN_SIZE = Long.MIN_VALUE;
-
- private long _size = UNKNOWN_SIZE;
-
-
-
- public String debugIdentity()
- {
- return "(HC:" + System.identityHashCode(this) + " ID:" + _messageId + " Ref:" + _referenceCount.get() + ")";
- }
-
- public void setExpiration()
- {
- long expiration =
- ((BasicContentHeaderProperties) _transientMessageData.getContentHeaderBody().properties).getExpiration();
- long timestamp =
- ((BasicContentHeaderProperties) _transientMessageData.getContentHeaderBody().properties).getTimestamp();
-
- if (SYNCED_CLOCKS)
- {
- _expiration = expiration;
- }
- else
- {
- // Update TTL to be in broker time.
- if (expiration != 0L)
- {
- if (timestamp != 0L)
- {
- // todo perhaps use arrival time
- long diff = (System.currentTimeMillis() - timestamp);
-
- if ((diff > 1000L) || (diff < 1000L))
- {
- _expiration = expiration + diff;
- }
- }
- }
- }
-
- }
-
- public boolean isReferenced()
- {
- return _referenceCount.get() > 0;
- }
-
- public void setExchange(final Exchange exchange)
- {
- _exchange = exchange;
- }
-
- public void route() throws AMQException
- {
- _exchange.route(this);
- }
-
- public void enqueue(final List<AMQQueue> queues)
- {
- _transientMessageData.setDestinationQueues(queues);
- }
/**
* Used to iterate through all the body frames associated with this message. Will not keep all the data in memory
@@ -172,7 +96,7 @@ public class AMQMessage
{
try
{
- return _index < (_messageHandle.getBodyCount(getStoreContext(), _messageId) - 1);
+ return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1);
}
catch (AMQException e)
{
@@ -189,7 +113,7 @@ public class AMQMessage
AMQBody cb =
getProtocolVersionMethodConverter().convertToBody(_messageHandle.getContentChunk(getStoreContext(),
- _messageId, ++_index));
+ ++_index));
return new AMQFrame(_channel, cb);
}
@@ -212,9 +136,14 @@ public class AMQMessage
}
}
+ public void clearStoreContext()
+ {
+ _storeContext = new StoreContext();
+ }
+
public StoreContext getStoreContext()
{
- return _txnContext.getStoreContext();
+ return _storeContext;
}
private class BodyContentIterator implements Iterator<ContentChunk>
@@ -226,7 +155,7 @@ public class AMQMessage
{
try
{
- return _index < (_messageHandle.getBodyCount(getStoreContext(), _messageId) - 1);
+ return _index < (_messageHandle.getBodyCount(getStoreContext()) - 1);
}
catch (AMQException e)
{
@@ -240,7 +169,7 @@ public class AMQMessage
{
try
{
- return _messageHandle.getContentChunk(getStoreContext(), _messageId, ++_index);
+ return _messageHandle.getContentChunk(getStoreContext(), ++_index);
}
catch (AMQException e)
{
@@ -254,13 +183,7 @@ public class AMQMessage
}
}
- public AMQMessage(Long messageId, MessagePublishInfo info, TransactionalContext txnContext)
- {
- _messageId = messageId;
- _txnContext = txnContext;
- _immediate = info.isImmediate();
- _transientMessageData.setMessagePublishInfo(info);
- }
+
/**
* Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal
@@ -276,141 +199,85 @@ public class AMQMessage
public AMQMessage(Long messageId, MessageStore store, MessageHandleFactory factory, TransactionalContext txnConext)
throws AMQException
{
- _messageId = messageId;
_messageHandle = factory.createMessageHandle(messageId, store, true);
- _txnContext = txnConext;
- _transientMessageData = null;
-
+ _storeContext = txnConext.getStoreContext();
+ _size = _messageHandle.getBodySize(txnConext.getStoreContext());
}
- /**
- * Used in testing only. This allows the passing of the content header immediately on construction.
+ /**
+ * Used when recovering, i.e. when the message store is creating references to messages. In that case, the normal
+ * enqueue/routingComplete is not done since the recovery process is responsible for routing the messages to
+ * queues.
*
- * @param messageId
- * @param info
- * @param txnContext
- * @param contentHeader
+ * @param messageHandle
+ *
+ * @throws AMQException
*/
- public AMQMessage(Long messageId, MessagePublishInfo info, TransactionalContext txnContext,
- ContentHeaderBody contentHeader) throws AMQException
+ public AMQMessage(
+ AMQMessageHandle messageHandle,
+ StoreContext storeConext,
+ MessagePublishInfo info)
+ throws AMQException
{
- this(messageId, info, txnContext);
- setContentHeaderBody(contentHeader);
- }
+ _messageHandle = messageHandle;
+ _storeContext = storeConext;
- /* *
- * Used in testing only. This allows the passing of the content header and some body fragments on construction.
- *
- * @param messageId
- * @param info
- * @param txnContext
- * @param contentHeader
- * @param destinationQueues
- * @param contentBodies
- *
- * @throws AMQException
- */ /*
- public AMQMessage(Long messageId, MessagePublishInfo info, TransactionalContext txnContext,
- ContentHeaderBody contentHeader, List<AMQQueue> destinationQueues, List<ContentChunk> contentBodies,
- MessageStore messageStore, StoreContext storeContext, MessageHandleFactory messageHandleFactory) throws AMQException
- {
- this(messageId, info, txnContext, contentHeader);
- _transientMessageData.setDestinationQueues(destinationQueues);
- routingComplete(messageStore, storeContext, messageHandleFactory);
- for (ContentChunk cb : contentBodies)
+ if(info.isImmediate())
{
- addContentBodyFrame(storeContext, cb);
+ _flags |= IMMEDIATE;
}
+ _size = messageHandle.getBodySize(storeConext);
+
}
- */
+
+
protected AMQMessage(AMQMessage msg) throws AMQException
{
- _messageId = msg._messageId;
_messageHandle = msg._messageHandle;
- _txnContext = msg._txnContext;
- _deliveredToConsumer = msg._deliveredToConsumer;
- _transientMessageData = msg._transientMessageData;
- }
+ _storeContext = msg._storeContext;
+ _flags = msg._flags;
+ _size = msg._size;
- public Iterator<AMQDataBlock> getBodyFrameIterator(AMQProtocolSession protocolSession, int channel)
- {
- return new BodyFrameIterator(protocolSession, channel);
}
- public Iterator<ContentChunk> getContentBodyIterator()
+
+ public String debugIdentity()
{
- return new BodyContentIterator();
+ return "(HC:" + System.identityHashCode(this) + " ID:" + getMessageId() + " Ref:" + _referenceCount.get() + ")";
}
- public ContentHeaderBody getContentHeaderBody() throws AMQException
+ public void setExpiration(final long expiration)
{
- if (_transientMessageData != null)
- {
- return _transientMessageData.getContentHeaderBody();
- }
- else
- {
- return _messageHandle.getContentHeaderBody(getStoreContext(), _messageId);
- }
+
+ _expiration = expiration;
+
}
- public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) throws AMQException
+ public boolean isReferenced()
{
- _transientMessageData.setContentHeaderBody(contentHeaderBody);
- _size = _transientMessageData.getContentHeaderBody().bodySize;
+ return _referenceCount.get() > 0;
}
- public void routingComplete(MessageStore store, StoreContext storeContext, MessageHandleFactory factory)
- throws AMQException
+ public Iterator<AMQDataBlock> getBodyFrameIterator(AMQProtocolSession protocolSession, int channel)
{
- final boolean persistent = isPersistent();
- _messageHandle = factory.createMessageHandle(_messageId, store, persistent);
- if (persistent)
- {
- _txnContext.beginTranIfNecessary();
- }
-
- // enqueuing the messages ensure that if required the destinations are recorded to a
- // persistent store
-
- for (AMQQueue q : _transientMessageData.getDestinationQueues())
- {
- _messageHandle.enqueue(storeContext, _messageId, q);
- }
-
- if (_transientMessageData.getContentHeaderBody().bodySize == 0)
- {
- deliver(storeContext);
- }
-
-
+ return new BodyFrameIterator(protocolSession, channel);
}
- public boolean addContentBodyFrame(StoreContext storeContext, ContentChunk contentChunk) throws AMQException
+ public Iterator<ContentChunk> getContentBodyIterator()
{
- _transientMessageData.addBodyLength(contentChunk.getSize());
- final boolean allContentReceived = isAllContentReceived();
- _messageHandle.addContentBodyFrame(storeContext, _messageId, contentChunk, allContentReceived);
- if (allContentReceived)
- {
- deliver(storeContext);
-
- return true;
- }
- else
- {
- return false;
- }
+ return new BodyContentIterator();
}
- public boolean isAllContentReceived() throws AMQException
+ public ContentHeaderBody getContentHeaderBody() throws AMQException
{
- return _transientMessageData.isAllContentReceived();
+ return _messageHandle.getContentHeaderBody(getStoreContext());
}
+
+
public Long getMessageId()
{
- return _messageId;
+ return _messageHandle.getMessageId();
}
/**
@@ -424,14 +291,24 @@ public class AMQMessage
return this;
}
- /** Threadsafe. Increment the reference count on the message. */
- public void incrementReference()
+ public boolean incrementReference()
+ {
+ return incrementReference(1);
+ }
+
+ /* Threadsafe. Increment the reference count on the message. */
+ public boolean incrementReference(int count)
{
- _referenceCount.incrementAndGet();
- // if (_log.isDebugEnabled())
- // {
- // _log.debug("Ref count on message " + debugIdentity() + " incremented " + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6));
- // }
+ if(_referenceCount.addAndGet(count) <= 1)
+ {
+ _referenceCount.addAndGet(-count);
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+
}
/**
@@ -445,6 +322,7 @@ public class AMQMessage
*/
public void decrementReference(StoreContext storeContext) throws MessageCleanupException
{
+
int count = _referenceCount.decrementAndGet();
// note that the operation of decrementing the reference count and then removing the message does not
@@ -453,25 +331,25 @@ public class AMQMessage
// not relying on the all the increments having taken place before the delivery manager decrements.
if (count == 0)
{
+ // set the reference count way below 0 so that we can detect that the message has been deleted
+ // this is to guard against the message being spontaneously recreated (from the mgmt console)
+ // by copying from other queues at the same time as it is being removed.
+ _referenceCount.set(Integer.MIN_VALUE/2);
+
try
{
- // if (_log.isDebugEnabled())
- // {
- // _log.debug("Decremented ref count on message " + debugIdentity() + " is zero; removing message" + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6));
- // }
-
// must check if the handle is null since there may be cases where we decide to throw away a message
// and the handle has not yet been constructed
if (_messageHandle != null)
{
- _messageHandle.removeMessage(storeContext, _messageId);
+ _messageHandle.removeMessage(storeContext);
}
}
catch (AMQException e)
{
// to maintain consistency, we revert the count
incrementReference();
- throw new MessageCleanupException(_messageId, e);
+ throw new MessageCleanupException(getMessageId(), e);
}
}
else
@@ -484,15 +362,6 @@ public class AMQMessage
}
}
- public void setPublisher(AMQProtocolSession publisher)
- {
- _publisher = publisher;
- }
-
- public AMQProtocolSession getPublisher()
- {
- return _publisher;
- }
/**
* Called selectors to determin if the message has already been sent
@@ -501,101 +370,30 @@ public class AMQMessage
*/
public boolean getDeliveredToConsumer()
{
- return _deliveredToConsumer;
- }
-
-
- public boolean checkToken(Object token)
- {
-
- if (_tokens == null)
- {
- _tokens = new HashSet<Object>();
- }
-
- if (_tokens.contains(token))
- {
- return true;
- }
- else
- {
- _tokens.add(token);
-
- return false;
- }
- }
-
- /**
- * Registers a queue to which this message is to be delivered. This is called from the exchange when it is routing
- * the message. This will be called before any content bodies have been received so that the choice of
- * AMQMessageHandle implementation can be picked based on various criteria.
- *
- * @param queue the queue
- *
- * @throws org.apache.qpid.AMQException if there is an error enqueuing the message
- */
- public void enqueue(AMQQueue queue) throws AMQException
- {
- _transientMessageData.addDestinationQueue(queue);
- }
-
- /**
- * NOTE: Think about why you are using this method. Normal usages would want to do
- * AMQQueue.dequeue(StoreContext, AMQMessage)
- * This will keep the queue statistics up-to-date.
- * Currently this method is only called _correctly_ from AMQQueue dequeue.
- * Ideally we would have a better way for the queue to dequeue the message.
- * Especially since enqueue isn't the recipriocal of this method.
- * @deprecated
- * @param storeContext
- * @param queue
- * @throws AMQException
- */
- void dequeue(StoreContext storeContext, AMQQueue queue) throws AMQException
- {
- _messageHandle.dequeue(storeContext, _messageId, queue);
+ return (_flags & DELIVERED_TO_CONSUMER) != 0;
}
public boolean isPersistent() throws AMQException
{
- if (_transientMessageData != null)
- {
- return _transientMessageData.isPersistent();
- }
- else
- {
- return _messageHandle.isPersistent(getStoreContext(), _messageId);
- }
+ return _messageHandle.isPersistent();
}
/**
* Called to enforce the 'immediate' flag.
*
- * @throws NoConsumersException if the message is marked for immediate delivery but has not been marked as delivered
+ * @returns true if the message is marked for immediate delivery but has not been marked as delivered
* to a consumer
*/
- public void checkDeliveredToConsumer() throws NoConsumersException
+ public boolean immediateAndNotDelivered()
{
- if (_immediate && !_deliveredToConsumer)
- {
- throw new NoConsumersException(this);
- }
+ return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE;
+
}
public MessagePublishInfo getMessagePublishInfo() throws AMQException
{
- MessagePublishInfo pb;
- if (_transientMessageData != null)
- {
- pb = _transientMessageData.getMessagePublishInfo();
- }
- else
- {
- pb = _messageHandle.getMessagePublishInfo(getStoreContext(), _messageId);
- }
-
- return pb;
+ return _messageHandle.getMessagePublishInfo(getStoreContext());
}
public boolean isRedelivered()
@@ -641,46 +439,9 @@ public class AMQMessage
*/
public void setDeliveredToConsumer()
{
- _deliveredToConsumer = true;
+ _flags |= DELIVERED_TO_CONSUMER;
}
- private void deliver(StoreContext storeContext) throws AMQException
- {
- // we get a reference to the destination queues now so that we can clear the
- // transient message data as quickly as possible
- List<AMQQueue> destinationQueues = _transientMessageData.getDestinationQueues();
- if (_log.isDebugEnabled())
- {
- _log.debug("Delivering message " + debugIdentity() + " to " + destinationQueues);
- }
-
- try
- {
- // first we allow the handle to know that the message has been fully received. This is useful if it is
- // maintaining any calculated values based on content chunks
- _messageHandle.setPublishAndContentHeaderBody(storeContext, _messageId,
- _transientMessageData.getMessagePublishInfo(), _transientMessageData.getContentHeaderBody());
-
- // we then allow the transactional context to do something with the message content
- // now that it has all been received, before we attempt delivery
- _txnContext.messageFullyReceived(isPersistent());
-
- for (AMQQueue q : destinationQueues)
- {
- // Increment the references to this message for each queue delivery.
- incrementReference();
- // normal deliver so add this message at the end.
- _txnContext.deliver(q.createEntry(this), false);
- }
- }
- finally
- {
-
- // Remove refence for routing process . Reference count should now == delivered queue count
- decrementReference(storeContext);
- _transientMessageData = null;
- }
- }
public AMQMessageHandle getMessageHandle()
@@ -690,28 +451,23 @@ public class AMQMessage
public long getSize()
{
- if(_size == UNKNOWN_SIZE)
- {
- try
- {
- _size = getContentHeaderBody().bodySize;
- }
- catch (AMQException e)
- {
- _log.warn("Unable to retrieve message meta data for message:" + this, e);
- return 0;
- }
- }
return _size;
+
+ }
+
+ public Object getPublisherClientInstance()
+ {
+ return _sessionIdentifier.getSessionInstance();
+ }
+
+ public Object getPublisherIdentifier()
+ {
+ return _sessionIdentifier.getSessionIdentifier();
}
- public void restoreTransientMessageData() throws AMQException
+ public void setClientIdentifier(final AMQProtocolSession.ProtocolSessionIdentifier sessionIdentifier)
{
- TransientMessageData transientMessageData = new TransientMessageData();
- transientMessageData.setMessagePublishInfo(getMessagePublishInfo());
- transientMessageData.setContentHeaderBody(getContentHeaderBody());
- transientMessageData.addBodyLength(getContentHeaderBody().getSize());
- _transientMessageData = transientMessageData;
+ _sessionIdentifier = sessionIdentifier;
}
@@ -720,7 +476,7 @@ public class AMQMessage
// return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken : " +
// _taken + " by :" + _takenBySubcription;
- return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount;
+ return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + _referenceCount;
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java
index ede55b3bbf..0ddd4e4d92 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessageHandle.java
@@ -29,23 +29,27 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo;
/**
* A pluggable way of getting message data. Implementations can provide intelligent caching for example or
* even no caching at all to minimise the broker memory footprint.
- *
- * The method all take a messageId to avoid having to store it in the instance - the AMQMessage container
- * must already keen the messageId so it is pointless storing it twice.
*/
public interface AMQMessageHandle
{
- ContentHeaderBody getContentHeaderBody(StoreContext context, Long messageId) throws AMQException;
+ ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException;
+
+ /**
+ *
+ * @return the messageId for the message associated with this handle
+ */
+ Long getMessageId();
+
/**
* @return the number of body frames associated with this message
*/
- int getBodyCount(StoreContext context, Long messageId) throws AMQException;
+ int getBodyCount(StoreContext context) throws AMQException;
/**
* @return the size of the body
*/
- long getBodySize(StoreContext context, Long messageId) throws AMQException;
+ long getBodySize(StoreContext context) throws AMQException;
/**
* Get a particular content body
@@ -53,27 +57,23 @@ public interface AMQMessageHandle
* @return a content body
* @throws IllegalArgumentException if the index is invalid
*/
- ContentChunk getContentChunk(StoreContext context, Long messageId, int index) throws IllegalArgumentException, AMQException;
+ ContentChunk getContentChunk(StoreContext context, int index) throws IllegalArgumentException, AMQException;
- void addContentBodyFrame(StoreContext storeContext, Long messageId, ContentChunk contentBody, boolean isLastContentBody) throws AMQException;
+ void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody) throws AMQException;
- MessagePublishInfo getMessagePublishInfo(StoreContext context, Long messageId) throws AMQException;
+ MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException;
boolean isRedelivered();
void setRedelivered(boolean redelivered);
- boolean isPersistent(StoreContext context, Long messageId) throws AMQException;
+ boolean isPersistent();
- void setPublishAndContentHeaderBody(StoreContext storeContext, Long messageId, MessagePublishInfo messagePublishInfo,
+ void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo,
ContentHeaderBody contentHeaderBody)
throws AMQException;
- void removeMessage(StoreContext storeContext, Long messageId) throws AMQException;
-
- void enqueue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException;
-
- void dequeue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException;
+ void removeMessage(StoreContext storeContext) throws AMQException;
long getArrivalTime();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
new file mode 100644
index 0000000000..e14ed0f41d
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
@@ -0,0 +1,71 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.subscription.SubscriptionList;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.AMQException;
+
+public class AMQPriorityQueue extends SimpleAMQQueue
+{
+ protected AMQPriorityQueue(final AMQShortString name,
+ final boolean durable,
+ final AMQShortString owner,
+ final boolean autoDelete,
+ final VirtualHost virtualHost,
+ int priorities)
+ throws AMQException
+ {
+ super(name, durable, owner, autoDelete, virtualHost, new PriorityQueueList.Factory(priorities));
+ }
+
+ public int getPriorities()
+ {
+ return ((PriorityQueueList) _entries).getPriorities();
+ }
+
+ @Override
+ protected void checkSubscriptionsNotAheadOfDelivery(final QueueEntry entry)
+ {
+ // check that all subscriptions are not in advance of the entry
+ SubscriptionList.SubscriptionNodeIterator subIter = _subscriptionList.iterator();
+ while(subIter.advance() && !entry.isAcquired())
+ {
+ final Subscription subscription = subIter.getNode().getSubscription();
+ QueueEntry subnode = subscription.getLastSeenEntry();
+ while((entry.compareTo(subnode) < 0) && !entry.isAcquired())
+ {
+ if(subscription.setLastSeenEntry(subnode,entry))
+ {
+ break;
+ }
+ else
+ {
+ subnode = subscription.getLastSeenEntry();
+ }
+ }
+
+ }
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 7c6db0b4b3..c9c252f06d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -20,1005 +20,191 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.configuration.Configured;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.management.Managable;
-import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
-import javax.management.JMException;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * This is an AMQ Queue, and should not be confused with a JMS queue or any other abstraction like that. It is described
- * fully in RFC 006.
- */
-public class AMQQueue implements Managable, Comparable
-{
-
- /**
- * ExistingExclusiveSubscription signals a failure to create a subscription, because an exclusive subscription
- * already exists.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create a subscription, because an exclusive subscription already exists.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Move to top level, used outside this class.
- */
- public static final class ExistingExclusiveSubscription extends AMQException
- {
-
- public ExistingExclusiveSubscription()
- {
- super("");
- }
- }
-
- /**
- * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusize subscription, as a subscription
- * already exists.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represent failure to create an exclusize subscription, as a subscription already exists.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Move to top level, used outside this class.
- */
- public static final class ExistingSubscriptionPreventsExclusive extends AMQException
- {
- public ExistingSubscriptionPreventsExclusive()
- {
- super("");
- }
- }
-
- private static final Logger _logger = Logger.getLogger(AMQQueue.class);
-
- private final AMQShortString _name;
-
- /** null means shared */
- private final AMQShortString _owner;
-
- private final boolean _durable;
-
- /** If true, this queue is deleted when the last subscriber is removed */
- private final boolean _autoDelete;
-
- /** Holds subscribers to the queue. */
- private final SubscriptionSet _subscribers;
-
- private final SubscriptionFactory _subscriptionFactory;
-
- private final AtomicInteger _subscriberCount = new AtomicInteger();
-
- private final AtomicBoolean _isExclusive = new AtomicBoolean();
-
- private final AtomicBoolean _deleted = new AtomicBoolean(false);
-
- private List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>();
-
- /** Manages message delivery. */
- private final DeliveryManager _deliveryMgr;
-
- /** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */
- private final ExchangeBindings _bindings = new ExchangeBindings(this);
-
- /** Executor on which asynchronous delivery will be carriedout where required */
- private final Executor _asyncDelivery;
-
- private final AMQQueueMBean _managedObject;
-
- private final VirtualHost _virtualHost;
-
- /** max allowed size(KB) of a single message */
- @Configured(path = "maximumMessageSize", defaultValue = "0")
- public long _maximumMessageSize;
-
- /** max allowed number of messages on a queue. */
- @Configured(path = "maximumMessageCount", defaultValue = "0")
- public long _maximumMessageCount;
-
- /** max queue depth for the queue */
- @Configured(path = "maximumQueueDepth", defaultValue = "0")
- public long _maximumQueueDepth;
-
- /** maximum message age before alerts occur */
- @Configured(path = "maximumMessageAge", defaultValue = "0")
- public long _maximumMessageAge;
-
- /** the minimum interval between sending out consequetive alerts of the same type */
- @Configured(path = "minimumAlertRepeatGap", defaultValue = "0")
- public long _minimumAlertRepeatGap;
-
- /** total messages received by the queue since startup. */
- public AtomicLong _totalMessagesReceived = new AtomicLong();
-
-
- private final Set<NotificationCheck> _notificationChecks = EnumSet.noneOf(NotificationCheck.class);
-
-
- public AMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost)
- throws AMQException
- {
- this(name, durable, owner, autoDelete, virtualHost, AsyncDeliveryConfig.getAsyncDeliveryExecutor(),
- new SubscriptionSet(), new SubscriptionImpl.Factory());
- }
-
- protected AMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete,
- VirtualHost virtualHost, SubscriptionSet subscribers) throws AMQException
- {
- this(name, durable, owner, autoDelete, virtualHost, AsyncDeliveryConfig.getAsyncDeliveryExecutor(), subscribers,
- new SubscriptionImpl.Factory());
- }
-
- protected AMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete,
- VirtualHost virtualHost, Executor asyncDelivery, SubscriptionSet subscribers,
- SubscriptionFactory subscriptionFactory) throws AMQException
- {
- if (name == null)
- {
- throw new IllegalArgumentException("Queue name must not be null");
- }
-
- if (virtualHost == null)
- {
- throw new IllegalArgumentException("Virtual Host must not be null");
- }
-
- _name = name;
- _durable = durable;
- _owner = owner;
- _autoDelete = autoDelete;
- _virtualHost = virtualHost;
- _asyncDelivery = asyncDelivery;
-
- _managedObject = createMBean();
- _managedObject.register();
-
- _subscribers = subscribers;
- _subscriptionFactory = subscriptionFactory;
- _deliveryMgr = new ConcurrentSelectorDeliveryManager(_subscribers, this);
-
- // This ensure that the notification checks for the configured alerts are created.
- setMaximumMessageAge(_maximumMessageAge);
- setMaximumMessageCount(_maximumMessageCount);
- setMaximumMessageSize(_maximumMessageSize);
- setMaximumQueueDepth(_maximumQueueDepth);
-
- }
-
- private AMQQueueMBean createMBean() throws AMQException
- {
- try
- {
- return new AMQQueueMBean(this);
- }
- catch (JMException ex)
- {
- throw new AMQException("AMQQueue MBean creation has failed ", ex);
- }
- }
-
- public final AMQShortString getName()
- {
- return _name;
- }
+import java.util.List;
+import java.util.Set;
- public boolean isShared()
- {
- return _owner == null;
- }
+public interface AMQQueue extends Managable, Comparable<AMQQueue>
+{
- public boolean isDurable()
- {
- return _durable;
- }
+ AMQShortString getName();
- public AMQShortString getOwner()
- {
- return _owner;
- }
+ boolean isDurable();
- public boolean isAutoDelete()
- {
- return _autoDelete;
- }
+ boolean isAutoDelete();
- public boolean isDeleted()
- {
- return _deleted.get();
- }
+ AMQShortString getOwner();
- /** @return no of messages(undelivered) on the queue. */
- public int getMessageCount()
- {
- return _deliveryMgr.getQueueMessageCount();
- }
+ VirtualHost getVirtualHost();
- /** @return List of messages(undelivered) on the queue. */
- public List<QueueEntry> getMessagesOnTheQueue()
- {
- return _deliveryMgr.getMessages();
- }
- /**
- * Returns messages within the given range of message Ids.
- *
- * @param fromMessageId
- * @param toMessageId
- *
- * @return List of messages
- */
- public List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId)
- {
- return _deliveryMgr.getMessages(fromMessageId, toMessageId);
- }
+ void bind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException;
- public long getQueueDepth()
- {
- return _deliveryMgr.getTotalMessageSize();
- }
+ void unBind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException;
- /**
- * @param messageId
- *
- * @return QueueEntry with give id if exists. null if QueueEntry with given id doesn't exist.
- */
- public QueueEntry getMessageOnTheQueue(long messageId)
- {
- List<QueueEntry> list = getMessagesOnTheQueue(messageId, messageId);
- if ((list == null) || (list.size() == 0))
- {
- return null;
- }
+ List<ExchangeBinding> getExchangeBindings();
- return list.get(0);
- }
- /**
- * Moves messages from this queue to another queue, and also commits the move on the message store. Delivery activity
- * on the queues being moved between is suspended during the move.
- *
- * @param fromMessageId The first message id to move.
- * @param toMessageId The last message id to move.
- * @param queueName The queue to move the messages to.
- * @param storeContext The context of the message store under which to perform the move. This is associated with
- * the stores transactional context.
- */
- public synchronized void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
- StoreContext storeContext)
- {
- AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+ void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException;
- MessageStore fromStore = getVirtualHost().getMessageStore();
- MessageStore toStore = toQueue.getVirtualHost().getMessageStore();
+ void unregisterSubscription(final Subscription subscription) throws AMQException;
- if (toStore != fromStore)
- {
- throw new RuntimeException("Can only move messages between queues on the same message store.");
- }
- try
- {
- // Obtain locks to prevent activity on the queues being moved between.
- startMovingMessages();
- toQueue.startMovingMessages();
-
- // Get the list of messages to move.
- List<QueueEntry> foundMessagesList = getMessagesOnTheQueue(fromMessageId, toMessageId);
-
- try
- {
- fromStore.beginTran(storeContext);
-
- // Move the messages in on the message store.
- for (QueueEntry entry : foundMessagesList)
- {
- AMQMessage message = entry.getMessage();
- fromStore.dequeueMessage(storeContext, _name, message.getMessageId());
- toStore.enqueueMessage(storeContext, toQueue._name, message.getMessageId());
- }
-
- // Commit and flush the move transcations.
- try
- {
- fromStore.commitTran(storeContext);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
- }
-
- // Move the messages on the in-memory queues.
- toQueue.enqueueMovedMessages(storeContext, foundMessagesList);
- _deliveryMgr.removeMovedMessages(foundMessagesList);
- }
- // Abort the move transactions on move failures.
- catch (AMQException e)
- {
- try
- {
- fromStore.abortTran(storeContext);
- }
- catch (AMQException ae)
- {
- throw new RuntimeException("Failed to abort transaction whilst moving messages on message store.", ae);
- }
- }
- }
- // Release locks to allow activity on the queues being moved between to continue.
- finally
- {
- toQueue.stopMovingMessages();
- stopMovingMessages();
- }
- }
-
- /**
- * Copies messages on this queue to another queue, and also commits the move on the message store. Delivery activity
- * on the queues being moved between is suspended during the move.
- *
- * @param fromMessageId The first message id to move.
- * @param toMessageId The last message id to move.
- * @param queueName The queue to move the messages to.
- * @param storeContext The context of the message store under which to perform the move. This is associated with
- * the stores transactional context.
- */
- public synchronized void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
- StoreContext storeContext)
- {
- AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
-
- MessageStore fromStore = getVirtualHost().getMessageStore();
- MessageStore toStore = toQueue.getVirtualHost().getMessageStore();
-
- if (toStore != fromStore)
- {
- throw new RuntimeException("Can only move messages between queues on the same message store.");
- }
+ int getConsumerCount();
- try
- {
- // Obtain locks to prevent activity on the queues being moved between.
- startMovingMessages();
- toQueue.startMovingMessages();
-
- // Get the list of messages to move.
- List<QueueEntry> foundMessagesList = getMessagesOnTheQueue(fromMessageId, toMessageId);
-
- try
- {
- fromStore.beginTran(storeContext);
-
- // Move the messages in on the message store.
- for (QueueEntry entry : foundMessagesList)
- {
- AMQMessage message = entry.getMessage();
- toStore.enqueueMessage(storeContext, toQueue._name, message.getMessageId());
- message.takeReference();
- }
-
- // Commit and flush the move transcations.
- try
- {
- fromStore.commitTran(storeContext);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
- }
-
- // Move the messages on the in-memory queues.
- toQueue.enqueueMovedMessages(storeContext, foundMessagesList);
- }
- // Abort the move transactions on move failures.
- catch (AMQException e)
- {
- try
- {
- fromStore.abortTran(storeContext);
- }
- catch (AMQException ae)
- {
- throw new RuntimeException("Failed to abort transaction whilst moving messages on message store.", ae);
- }
- }
- }
- // Release locks to allow activity on the queues being moved between to continue.
- finally
- {
- toQueue.stopMovingMessages();
- stopMovingMessages();
- }
- }
-
- /**
- * Removes messages from this queue, and also commits the remove on the message store. Delivery activity
- * on the queues being moved between is suspended during the remove.
- *
- * @param fromMessageId The first message id to move.
- * @param toMessageId The last message id to move.
- * @param storeContext The context of the message store under which to perform the move. This is associated with
- * the stores transactional context.
- */
- public synchronized void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext)
- {
- MessageStore fromStore = getVirtualHost().getMessageStore();
+ int getActiveConsumerCount();
- try
- {
- // Obtain locks to prevent activity on the queues being moved between.
- startMovingMessages();
-
- // Get the list of messages to move.
- List<QueueEntry> foundMessagesList = getMessagesOnTheQueue(fromMessageId, toMessageId);
-
- try
- {
- fromStore.beginTran(storeContext);
-
- // remove the messages in on the message store.
- for (QueueEntry entry : foundMessagesList)
- {
- AMQMessage message = entry.getMessage();
- fromStore.dequeueMessage(storeContext, _name, message.getMessageId());
- }
-
- // Commit and flush the move transcations.
- try
- {
- fromStore.commitTran(storeContext);
- }
- catch (AMQException e)
- {
- throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
- }
-
- // remove the messages on the in-memory queues.
- _deliveryMgr.removeMovedMessages(foundMessagesList);
- }
- // Abort the move transactions on move failures.
- catch (AMQException e)
- {
- try
- {
- fromStore.abortTran(storeContext);
- }
- catch (AMQException ae)
- {
- throw new RuntimeException("Failed to abort transaction whilst moving messages on message store.", ae);
- }
- }
- }
- // Release locks to allow activity on the queues being moved between to continue.
- finally
- {
- stopMovingMessages();
- }
- }
+ boolean isUnused();
- public void startMovingMessages()
- {
- _deliveryMgr.startMovingMessages();
- }
+ boolean isEmpty();
- private void enqueueMovedMessages(StoreContext storeContext, List<QueueEntry> messageList)
- {
- _deliveryMgr.enqueueMovedMessages(storeContext, messageList);
- _totalMessagesReceived.addAndGet(messageList.size());
- }
+ int getMessageCount();
- public void stopMovingMessages()
- {
- _deliveryMgr.stopMovingMessages();
- _deliveryMgr.processAsync(_asyncDelivery);
- }
+ int getUndeliveredMessageCount();
- /** @return MBean object associated with this Queue */
- public ManagedObject getManagedObject()
- {
- return _managedObject;
- }
- public long getMaximumMessageSize()
- {
- return _maximumMessageSize;
- }
+ long getQueueDepth();
- public void setMaximumMessageSize(final long maximumMessageSize)
- {
- _maximumMessageSize = maximumMessageSize;
- if(maximumMessageSize == 0L)
- {
- _notificationChecks.remove(NotificationCheck.MESSAGE_SIZE_ALERT);
- }
- else
- {
- _notificationChecks.add(NotificationCheck.MESSAGE_SIZE_ALERT);
- }
- }
+ long getReceivedMessageCount();
- public int getConsumerCount()
- {
- return _subscribers.size();
- }
+ long getOldestMessageArrivalTime();
- public int getActiveConsumerCount()
- {
- return _subscribers.getWeight();
- }
+ boolean isDeleted();
- public long getReceivedMessageCount()
- {
- return _totalMessagesReceived.get();
- }
- public long getMaximumMessageCount()
- {
- return _maximumMessageCount;
- }
+ int delete() throws AMQException;
- public void setMaximumMessageCount(final long maximumMessageCount)
- {
- _maximumMessageCount = maximumMessageCount;
- if(maximumMessageCount == 0L)
- {
- _notificationChecks.remove(NotificationCheck.MESSAGE_COUNT_ALERT);
- }
- else
- {
- _notificationChecks.add(NotificationCheck.MESSAGE_COUNT_ALERT);
- }
+ QueueEntry enqueue(StoreContext storeContext, AMQMessage message) throws AMQException;
+ void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException;
- }
+ void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException;
- public long getMaximumQueueDepth()
- {
- return _maximumQueueDepth;
- }
- // Sets the queue depth, the max queue size
- public void setMaximumQueueDepth(final long maximumQueueDepth)
- {
- _maximumQueueDepth = maximumQueueDepth;
- if(maximumQueueDepth == 0L)
- {
- _notificationChecks.remove(NotificationCheck.QUEUE_DEPTH_ALERT);
- }
- else
- {
- _notificationChecks.add(NotificationCheck.QUEUE_DEPTH_ALERT);
- }
- }
+ boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
- public long getOldestMessageArrivalTime()
- {
- return _deliveryMgr.getOldestMessageArrival();
+
- }
+ void addQueueDeleteTask(final Task task);
- /** Removes the QueueEntry from the top of the queue. */
- public synchronized void deleteMessageFromTop(StoreContext storeContext) throws AMQException
- {
- _deliveryMgr.removeAMessageFromTop(storeContext, this);
- }
- /** removes all the messages from the queue. */
- public synchronized long clearQueue(StoreContext storeContext) throws AMQException
- {
- return _deliveryMgr.clearAllMessages(storeContext);
- }
+ List<QueueEntry> getMessagesOnTheQueue();
- public void bind(AMQShortString routingKey, FieldTable arguments, Exchange exchange) throws AMQException
- {
- exchange.registerQueue(routingKey, this, arguments);
- if (isDurable() && exchange.isDurable())
- {
- _virtualHost.getMessageStore().bindQueue(exchange, routingKey, this, arguments);
- }
+ List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId);
- _bindings.addBinding(routingKey, arguments, exchange);
- }
+ List<Long> getMessagesOnTheQueue(int num);
- public void unBind(AMQShortString routingKey, FieldTable arguments, Exchange exchange) throws AMQException
- {
- exchange.deregisterQueue(routingKey, this, arguments);
- if (isDurable() && exchange.isDurable())
- {
- _virtualHost.getMessageStore().unbindQueue(exchange, routingKey, this, arguments);
- }
+ List<Long> getMessagesOnTheQueue(int num, int offest);
- _bindings.remove(routingKey, arguments, exchange);
- }
+ QueueEntry getMessageOnTheQueue(long messageId);
- public void registerProtocolSession(AMQProtocolSession ps, int channel, AMQShortString consumerTag, boolean acks,
- FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException
- {
- if (incrementSubscriberCount() > 1)
- {
- if (isExclusive())
- {
- decrementSubscriberCount();
- throw new ExistingExclusiveSubscription();
- }
- else if (exclusive)
- {
- decrementSubscriberCount();
- throw new ExistingSubscriptionPreventsExclusive();
- }
- }
- else if (exclusive)
- {
- setExclusive(true);
- }
+ void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName,
+ StoreContext storeContext);
- if (_logger.isDebugEnabled())
- {
- _logger.debug(MessageFormat.format("Registering protocol session {0} with channel {1} and "
- + "consumer tag {2} with {3}", ps, channel, consumerTag, this));
- }
+ void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName, StoreContext storeContext);
- Subscription subscription =
- _subscriptionFactory.createSubscription(channel, ps, consumerTag, acks, filters, noLocal, this);
+ void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext);
- if (subscription.filtersMessages())
- {
- if (_deliveryMgr.hasQueuedMessages())
- {
- _deliveryMgr.populatePreDeliveryQueue(subscription);
- }
- }
- _subscribers.addSubscriber(subscription);
- if(exclusive)
- {
- _subscribers.setExclusive(true);
- }
- subscription.start();
- }
+ long getMaximumMessageSize();
- private boolean isExclusive()
- {
- return _isExclusive.get();
- }
+ void setMaximumMessageSize(long value);
- private void setExclusive(boolean exclusive)
- {
- _isExclusive.set(exclusive);
- }
- private int incrementSubscriberCount()
- {
- return _subscriberCount.incrementAndGet();
- }
+ long getMaximumMessageCount();
- private int decrementSubscriberCount()
- {
- return _subscriberCount.decrementAndGet();
- }
+ void setMaximumMessageCount(long value);
- public void unregisterProtocolSession(AMQProtocolSession ps, int channel, AMQShortString consumerTag) throws AMQException
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug(MessageFormat.format(
- "Unregistering protocol session {0} with channel {1} and consumer tag {2} from {3}",
- ps, channel, consumerTag, this));
- }
- _subscribers.setExclusive(false);
- Subscription removedSubscription;
- if ((removedSubscription = _subscribers.removeSubscriber(_subscriptionFactory.createSubscription(channel, ps,
- consumerTag)))
- == null)
- {
- throw new AMQException("Protocol session with channel " + channel + " and consumer tag " + consumerTag
- + " and protocol session key " + ps.getKey() + " not registered with queue " + this);
- }
+ long getMaximumQueueDepth();
- removedSubscription.close();
- setExclusive(false);
- decrementSubscriberCount();
+ void setMaximumQueueDepth(long value);
- // if we are eligible for auto deletion, unregister from the queue registry
- if (_autoDelete && _subscribers.isEmpty())
- {
- if (_logger.isInfoEnabled())
- {
- _logger.info("Auto-deleteing queue:" + this);
- }
-
- autodelete();
- // we need to manually fire the event to the removed subscription (which was the last one left for this
- // queue. This is because the delete method uses the subscription set which has just been cleared
- removedSubscription.queueDeleted(this);
- }
- }
- public boolean isUnused()
- {
- return _subscribers.isEmpty();
- }
+ long getMaximumMessageAge();
- public boolean isEmpty()
- {
- return !_deliveryMgr.hasQueuedMessages();
- }
+ void setMaximumMessageAge(final long maximumMessageAge);
- public int delete(boolean checkUnused, boolean checkEmpty) throws AMQException
- {
- if (checkUnused && !_subscribers.isEmpty())
- {
- _logger.info("Will not delete " + this + " as it is in use.");
- return 0;
- }
- else if (checkEmpty && _deliveryMgr.hasQueuedMessages())
- {
- _logger.info("Will not delete " + this + " as it is not empty.");
+ long getMinimumAlertRepeatGap();
- return 0;
- }
- else
- {
- delete();
- return _deliveryMgr.getQueueMessageCount();
- }
- }
+ void deleteMessageFromTop(StoreContext storeContext) throws AMQException;
- public void delete() throws AMQException
- {
- if (!_deleted.getAndSet(true))
- {
- _subscribers.queueDeleted(this);
- _bindings.deregister();
- _virtualHost.getQueueRegistry().unregisterQueue(_name);
- _managedObject.unregister();
- for (Task task : _deleteTaskList)
- {
- task.doTask(this);
- }
-
- _deleteTaskList.clear();
- }
- }
+ long clearQueue(StoreContext storeContext) throws AMQException;
- protected void autodelete() throws AMQException
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug(MessageFormat.format("autodeleting {0}", this));
- }
- delete();
- }
- /*public void processGet(StoreContext storeContext, AMQMessage msg, boolean deliverFirst) throws AMQException
- {
- // fixme not sure what this is doing. should we be passing deliverFirst through here?
- // This code is not used so when it is perhaps it should
- _deliveryMgr.deliver(storeContext, getName(), msg, deliverFirst);
- try
- {
- msg.checkDeliveredToConsumer();
- updateReceivedMessageCount(msg);
- }
- catch (NoConsumersException e)
- {
- // as this message will be returned, it should be removed
- // from the queue:
- dequeue(storeContext, msg);
- }
- }*/
+ void removeExpiredIfNoSubscribers() throws AMQException;
- // public DeliveryManager getDeliveryManager()
- // {
- // return _deliveryMgr;
- // }
+ Set<NotificationCheck> getNotificationChecks();
- public void process(StoreContext storeContext, QueueEntry entry, boolean deliverFirst) throws AMQException
- {
- AMQMessage msg = entry.getMessage();
- _deliveryMgr.deliver(storeContext, _name, entry, deliverFirst);
- try
- {
- msg.checkDeliveredToConsumer();
- updateReceivedMessageCount(entry);
- }
- catch (NoConsumersException e)
- {
- // as this message will be returned, it should be removed
- // from the queue:
- dequeue(storeContext, entry);
- }
- }
+ void flushSubscription(final Subscription sub) throws AMQException;
- public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException
- {
- try
- {
- entry.getMessage().dequeue(storeContext, this);
- }
- catch (MessageCleanupException e)
- {
- // Message was dequeued, but could not then be deleted
- // though it is no longer referenced. This should be very
- // rare and can be detected and cleaned up on recovery or
- // done through some form of manual intervention.
- _logger.error(e, e);
- }
- catch (AMQException e)
- {
- throw new FailedDequeueException(_name.toString(), e);
- }
- }
+ void deliverAsync(final Subscription sub);
- public void deliverAsync()
- {
- _deliveryMgr.processAsync(_asyncDelivery);
- }
+ void deliverAsync();
- protected SubscriptionManager getSubscribers()
- {
- return _subscribers;
- }
- protected void updateReceivedMessageCount(QueueEntry entry) throws AMQException
+ /**
+ * ExistingExclusiveSubscription signals a failure to create a subscription, because an exclusive subscription
+ * already exists.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represent failure to create a subscription, because an exclusive subscription already exists.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Move to top level, used outside this class.
+ */
+ static final class ExistingExclusiveSubscription extends AMQException
{
- AMQMessage msg = entry.getMessage();
-
- if (!msg.isRedelivered())
- {
- _totalMessagesReceived.incrementAndGet();
- }
- try
- {
- _managedObject.checkForNotification(msg);
- }
- catch (JMException e)
+ public ExistingExclusiveSubscription()
{
- throw new AMQException("Unable to get notification from manage queue: " + e, e);
+ super("");
}
}
- public boolean equals(Object o)
+ /**
+ * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusize subscription, as a subscription
+ * already exists.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represent failure to create an exclusize subscription, as a subscription already exists.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Move to top level, used outside this class.
+ */
+ static final class ExistingSubscriptionPreventsExclusive extends AMQException
{
- if (this == o)
- {
- return true;
- }
-
- if ((o == null) || (getClass() != o.getClass()))
+ public ExistingSubscriptionPreventsExclusive()
{
- return false;
+ super("");
}
-
- final AMQQueue amqQueue = (AMQQueue) o;
-
- return (_name.equals(amqQueue._name));
- }
-
- public int hashCode()
- {
- return _name.hashCode();
}
- public String toString()
- {
- return "Queue(" + _name + ")@" + System.identityHashCode(this);
- }
-
- public boolean performGet(AMQProtocolSession session, AMQChannel channel, boolean acks) throws AMQException
- {
- return _deliveryMgr.performGet(session, channel, acks);
- }
-
- public QueueRegistry getQueueRegistry()
- {
- return _virtualHost.getQueueRegistry();
- }
-
- public VirtualHost getVirtualHost()
- {
- return _virtualHost;
- }
-
- public static interface Task
+ static interface Task
{
public void doTask(AMQQueue queue) throws AMQException;
}
-
- public void addQueueDeleteTask(Task task)
- {
- _deleteTaskList.add(task);
- }
-
- public long getMinimumAlertRepeatGap()
- {
- return _minimumAlertRepeatGap;
- }
-
- public void setMinimumAlertRepeatGap(long minimumAlertRepeatGap)
- {
- _minimumAlertRepeatGap = minimumAlertRepeatGap;
- }
-
- public long getMaximumMessageAge()
- {
- return _maximumMessageAge;
- }
-
- public void setMaximumMessageAge(long maximumMessageAge)
- {
- _maximumMessageAge = maximumMessageAge;
- if(maximumMessageAge == 0L)
- {
- _notificationChecks.remove(NotificationCheck.MESSAGE_AGE_ALERT);
- }
- else
- {
- _notificationChecks.add(NotificationCheck.MESSAGE_AGE_ALERT);
- }
- }
-
- public void subscriberHasPendingResend(boolean hasContent, SubscriptionImpl subscription, QueueEntry entry)
- {
- _deliveryMgr.subscriberHasPendingResend(hasContent, subscription, entry);
- }
-
- public QueueEntry createEntry(AMQMessage amqMessage)
- {
- return new QueueEntry(this, amqMessage);
- }
-
- public int compareTo(Object o)
- {
- return _name.compareTo(((AMQQueue) o).getName());
- }
-
-
- public void removeExpiredIfNoSubscribers() throws AMQException
- {
- synchronized(_subscribers.getChangeLock())
- {
- if(_subscribers.isEmpty())
- {
- _deliveryMgr.removeExpired();
- }
- }
- }
-
- public final Set<NotificationCheck> getNotificationChecks()
- {
- return _notificationChecks;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
new file mode 100644
index 0000000000..9dfc4449bb
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.AMQException;
+
+
+public class AMQQueueFactory
+{
+ public static final AMQShortString X_QPID_PRIORITIES = new AMQShortString("x-qpid-priorities");
+
+ public static AMQQueue createAMQQueueImpl(AMQShortString name,
+ boolean durable,
+ AMQShortString owner,
+ boolean autoDelete,
+ VirtualHost virtualHost, final FieldTable arguments)
+ throws AMQException
+ {
+
+ final int priorities = arguments == null ? 1 : arguments.containsKey(X_QPID_PRIORITIES) ? arguments.getInteger(X_QPID_PRIORITIES) : 1;
+
+ if(priorities > 1)
+ {
+ return new AMQPriorityQueue(name, durable, owner, autoDelete, virtualHost, priorities);
+ }
+ else
+ {
+ return new SimpleAMQQueue(name, durable, owner, autoDelete, virtualHost);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index 348a136f9d..2ed6be77c6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -292,7 +292,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
}
/**
- * @see org.apache.qpid.server.queue.AMQQueue#deleteMessageFromTop
+ * @see AMQQueue#deleteMessageFromTop
*/
public void deleteMessageFromTop() throws JMException
{
@@ -307,7 +307,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
}
/**
- * @see org.apache.qpid.server.queue.AMQQueue#clearQueue
+ * @see AMQQueue#clearQueue
*/
public void clearQueue() throws JMException
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java
deleted file mode 100644
index 0e8cff0f2a..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java
+++ /dev/null
@@ -1,1097 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.configuration.Configured;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.configuration.Configurator;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.util.ConcurrentLinkedMessageQueueAtomicSize;
-import org.apache.qpid.util.MessageQueue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.ReentrantLock;
-
-
-/** Manages delivery of messages on behalf of a queue */
-public class ConcurrentSelectorDeliveryManager implements DeliveryManager
-{
- private static final Logger _log = Logger.getLogger(ConcurrentSelectorDeliveryManager.class);
-
- @Configured(path = "advanced.compressBufferOnQueue",
- defaultValue = "false")
- public boolean compressBufferOnQueue;
- /** Holds any queued messages */
- private final MessageQueue<QueueEntry> _messages = new ConcurrentLinkedMessageQueueAtomicSize<QueueEntry>();
-
- /** Ensures that only one asynchronous task is running for this manager at any time. */
- private final AtomicBoolean _processing = new AtomicBoolean();
- /** The subscriptions on the queue to whom messages are delivered */
- private final SubscriptionManager _subscriptions;
-
- /**
- * A reference to the queue we are delivering messages for. We need this to be able to pass the code that handles
- * acknowledgements a handle on the queue.
- */
- private final AMQQueue _queue;
-
- /**
- * Flag used while moving messages from this queue to another. For moving messages the async delivery should also
- * stop. This flat should be set to true to stop async delivery and set to false to enable async delivery again.
- */
- private AtomicBoolean _movingMessages = new AtomicBoolean();
-
- /**
- * Lock used to ensure that an channel that becomes unsuspended during the start of the queueing process is forced
- * to wait till the first message is added to the queue. This will ensure that the _queue has messages to be
- * delivered via the async thread. <p/> Lock is used to control access to hasQueuedMessages() and over the addition
- * of messages to the queue.
- */
- private ReentrantLock _lock = new ReentrantLock();
- private AtomicLong _totalMessageSize = new AtomicLong();
- private AtomicInteger _extraMessages = new AtomicInteger();
- private Set<Subscription> _hasContent = Collections.synchronizedSet(new HashSet<Subscription>());
- private final Object _queueHeadLock = new Object();
- private String _processingThreadName = "";
-
- ConcurrentSelectorDeliveryManager(SubscriptionManager subscriptions, AMQQueue queue)
- {
-
- //Set values from configuration
- Configurator.configure(this);
-
- if (compressBufferOnQueue)
- {
- _log.warn("Compressing Buffers on queue.");
- }
-
- _subscriptions = subscriptions;
- _queue = queue;
- }
-
-
- private boolean addMessageToQueue(QueueEntry entry, boolean deliverFirst)
- {
- AMQMessage msg = entry.getMessage();
- // Shrink the ContentBodies to their actual size to save memory.
- if (compressBufferOnQueue)
- {
- Iterator<ContentChunk> it = msg.getContentBodyIterator();
- while (it.hasNext())
- {
- ContentChunk cb = it.next();
- cb.reduceToFit();
- }
- }
-
- if (deliverFirst)
- {
- synchronized (_queueHeadLock)
- {
- _messages.pushHead(entry);
- }
- }
- else
- {
- _messages.offer(entry);
- }
-
- _totalMessageSize.addAndGet(msg.getSize());
-
- return true;
- }
-
-
- public boolean hasQueuedMessages()
- {
- _lock.lock();
- try
- {
- return !(_messages.isEmpty() && _hasContent.isEmpty());
- }
- finally
- {
- _lock.unlock();
- }
- }
-
- public int getQueueMessageCount()
- {
- return getMessageCount();
- }
-
- /**
- * This is an EXPENSIVE opperation to perform with a ConcurrentLinkedQueue as it must run the queue to determine
- * size. The ConcurrentLinkedQueueAtomicSize uses an AtomicInteger to record the number of elements on the queue.
- *
- * @return int the number of messages in the delivery queue.
- */
- private int getMessageCount()
- {
- return _messages.size() + _extraMessages.get();
- }
-
-
- public long getTotalMessageSize()
- {
- return _totalMessageSize.get();
- }
-
- public long getOldestMessageArrival()
- {
- QueueEntry entry = _messages.peek();
- return entry == null ? Long.MAX_VALUE : entry.getMessage().getArrivalTime();
- }
-
- public void subscriberHasPendingResend(boolean hasContent, Subscription subscription, QueueEntry entry)
- {
- _lock.lock();
- try
- {
- if (hasContent)
- {
- _log.debug("Queue has adding subscriber content");
- _hasContent.add(subscription);
- _totalMessageSize.addAndGet(entry.getSize());
- _extraMessages.addAndGet(1);
- }
- else
- {
- _log.debug("Queue has removing subscriber content");
- if (entry == null)
- {
- _hasContent.remove(subscription);
- }
- else
- {
- _totalMessageSize.addAndGet(-entry.getSize());
- _extraMessages.addAndGet(-1);
- }
- }
- }
- finally
- {
- _lock.unlock();
- }
- }
-
- /**
- * NOTE : This method should only be called when there are no active subscribers
- */
- public void removeExpired() throws AMQException
- {
- _lock.lock();
- try
- {
- // New Context to for dealing with the MessageStore.
- StoreContext context = new StoreContext();
-
- for(Iterator<QueueEntry> iter = _messages.iterator(); iter.hasNext();)
- {
- QueueEntry entry = iter.next();
- if(entry.expired())
- {
- // fixme: Currently we have to update the total byte size here for the data in the queue
- _totalMessageSize.addAndGet(-entry.getSize());
-
- // Remove the message from the queue in the MessageStore
- _queue.dequeue(context,entry);
-
- // This queue nolonger needs a reference to this message
- entry.getMessage().decrementReference(context);
- iter.remove();
- }
- }
- }
- finally
- {
- _lock.unlock();
- }
- }
-
- /** @return the state of the async processor. */
- public boolean isProcessingAsync()
- {
- return _processing.get();
- }
-
- /**
- * Returns all the messages in the Queue
- *
- * @return List of messages
- */
- public List<QueueEntry> getMessages()
- {
- List<QueueEntry> list = new ArrayList<QueueEntry>();
-
- _lock.lock();
- try
- {
- for (QueueEntry entry : _messages)
- {
- list.add(entry);
- }
- }
- finally
- {
- _lock.unlock();
- }
-
- return list;
- }
-
- /**
- * Returns messages within the range of given messageIds
- *
- * @param fromMessageId
- * @param toMessageId
- *
- * @return
- */
- public List<QueueEntry> getMessages(long fromMessageId, long toMessageId)
- {
- if (fromMessageId <= 0 || toMessageId <= 0)
- {
- return null;
- }
-
- long maxMessageCount = toMessageId - fromMessageId + 1;
-
- List<QueueEntry> foundMessagesList = new ArrayList<QueueEntry>();
- _lock.lock();
- try
- {
- for (QueueEntry entry : _messages)
- {
- long msgId = entry.getMessage().getMessageId();
- if (msgId >= fromMessageId && msgId <= toMessageId)
- {
- foundMessagesList.add(entry);
- }
- // break if the no of messages are found
- if (foundMessagesList.size() == maxMessageCount)
- {
- break;
- }
- }
- }
- finally
- {
- _lock.unlock();
- }
-
- return foundMessagesList;
- }
-
- public void populatePreDeliveryQueue(Subscription subscription)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Populating PreDeliveryQueue for Subscription(" + System.identityHashCode(subscription) + ")");
- }
-
- Iterator<QueueEntry> currentQueue = _messages.iterator();
-
- while (currentQueue.hasNext())
- {
- QueueEntry entry = currentQueue.next();
-
- if (subscription.hasInterest(entry))
- {
- subscription.enqueueForPreDelivery(entry, false);
- }
-
- }
- }
-
- public boolean performGet(AMQProtocolSession protocolSession, AMQChannel channel, boolean acks) throws AMQException
- {
- QueueEntry entry = getNextMessage();
- if (entry == null)
- {
- return false;
- }
- else
- {
-
- try
- {
- // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
-
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
- if (!acks)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("No ack mode so dequeuing message immediately: " + entry.getMessage().getMessageId());
- }
- _queue.dequeue(channel.getStoreContext(), entry);
- }
- synchronized (channel)
- {
- long deliveryTag = channel.getNextDeliveryTag();
-
- if (acks)
- {
- channel.addUnacknowledgedMessage(entry, deliveryTag, null);
- }
-
- protocolSession.getProtocolOutputConverter().writeGetOk(entry.getMessage(), channel.getChannelId(),
- deliveryTag, _queue.getMessageCount());
-
- }
- _totalMessageSize.addAndGet(-entry.getSize());
-
- if (!acks)
- {
- entry.getMessage().decrementReference(channel.getStoreContext());
- }
- }
- finally
- {
- entry.setDeliveredToConsumer();
- }
- return true;
-
- }
- }
-
- /**
- * For feature of moving messages, this method is used. It sets the lock and sets the movingMessages flag, so that
- * the asyn delivery is also stopped.
- */
- public void startMovingMessages()
- {
- _movingMessages.set(true);
- }
-
- /**
- * Once moving messages to another queue is done or aborted, remove lock and unset the movingMessages flag, so that
- * the async delivery can start again.
- */
- public void stopMovingMessages()
- {
- _movingMessages.set(false);
- if (_lock.isHeldByCurrentThread())
- {
- _lock.unlock();
- }
- }
-
- /**
- * Messages will be removed from this queue and all preDeliveryQueues
- *
- * @param messageList
- */
- public void removeMovedMessages(List<QueueEntry> messageList)
- {
- // Remove from the
- boolean hasSubscribers = _subscriptions.hasActiveSubscribers();
- if (hasSubscribers)
- {
- for (Subscription sub : _subscriptions.getSubscriptions())
- {
- if (!sub.isSuspended() && sub.filtersMessages())
- {
- Queue<QueueEntry> preDeliveryQueue = sub.getPreDeliveryQueue();
- for (QueueEntry entry : messageList)
- {
- preDeliveryQueue.remove(entry);
- }
- }
- }
- }
-
- for (QueueEntry entry : messageList)
- {
- if (_messages.remove(entry))
- {
- _totalMessageSize.getAndAdd(-entry.getSize());
- }
- }
- }
-
- /**
- * Now with implementation of predelivery queues, this method will mark the message on the top as taken.
- *
- * @param storeContext
- *
- * @throws AMQException
- */
- public void removeAMessageFromTop(StoreContext storeContext, AMQQueue queue) throws AMQException
- {
- _lock.lock();
-
- try
- {
- QueueEntry entry = _messages.poll();
-
- if (entry != null)
- {
- queue.dequeue(storeContext, entry);
-
- _totalMessageSize.addAndGet(-entry.getSize());
-
- //If this causes ref count to hit zero then data will be purged so message.getSize() will NPE.
- entry.getMessage().decrementReference(storeContext);
-
- }
- }
- finally
- {
- _lock.unlock();
- }
- }
-
- public long clearAllMessages(StoreContext storeContext) throws AMQException
- {
- long count = 0;
-
- _lock.lock();
- try
- {
- synchronized (_queueHeadLock)
- {
- QueueEntry entry = getNextMessage();
-
- // todo: note: why do we need this? Why not reuse the passed 'storeContext'
- //Create a new StoreContext for decrementing the References
- StoreContext context = new StoreContext();
-
- while (entry != null)
- {
- //and remove it
- _messages.poll();
-
- // todo: NOTE: Why is this a different context to the new local 'context'?
- _queue.dequeue(storeContext, entry);
-
- entry.getMessage().decrementReference(context);
-
- entry = getNextMessage();
- count++;
- }
- _totalMessageSize.set(0L);
- }
- }
- finally
- {
- _lock.unlock();
- }
- return count;
- }
-
- /**
- * This can only be used to clear the _messages queue. Any subscriber resend queue will not be purged.
- *
- * @return the next message or null
- *
- * @throws org.apache.qpid.AMQException
- */
- private QueueEntry getNextMessage() throws AMQException
- {
- return getNextMessage(_messages, null, false);
- }
-
- private QueueEntry getNextMessage(Queue<QueueEntry> messages, Subscription sub, boolean purgeOnly) throws AMQException
- {
- QueueEntry entry = messages.peek();
-
- //while (we have a message) && ((The subscriber is not a browser or message is taken ) or we are clearing) && (Check message is taken.)
- while (purgeMessage(entry, sub, purgeOnly))
- {
- AMQMessage message = entry.getMessage();
-
- //remove the already taken message or expired
- QueueEntry removed = messages.poll();
-
- assert removed == entry;
-
- // if the message expired then the _totalMessageSize needs adjusting
- if (message.expired(_queue) && !entry.taken(sub))
- {
- _totalMessageSize.addAndGet(-entry.getSize());
-
- // New Store Context for removing expired messages
- StoreContext storeContext = new StoreContext();
-
- // Use the reapingStoreContext as any sub(if we have one) may be in a tx.
- _queue.dequeue(storeContext, entry);
-
- message.decrementReference(storeContext);
-
- if (_log.isInfoEnabled())
- {
- _log.info(debugIdentity() + " Doing clean up of the main _message queue.");
- }
- }
-
- //else the clean up is not required as the message has already been taken for this queue therefore
- // it was the responsibility of the code that took the message to ensure the _totalMessageSize was updated.
-
- if (_log.isDebugEnabled())
- {
- _log.debug("Removed taken message:" + message.debugIdentity());
- }
-
- // try the next message
- entry = messages.peek();
- }
-
- return entry;
- }
-
- /**
- * This method will return true if the message is to be purged from the queue.
- *
- *
- * SIDE-EFFECT: The message will be taken by the Subscription(sub) for the current Queue(_queue)
- *
- * @param message
- * @param sub
- *
- * @return
- *
- * @throws AMQException
- */
- private boolean purgeMessage(QueueEntry message, Subscription sub) throws AMQException
- {
- return purgeMessage(message, sub, false);
- }
-
- /**
- * This method will return true if the message is to be purged from the queue.
- * \
- * SIDE-EFFECT: The msg will be taken by the Subscription(sub) for the current Queue(_queue) when purgeOnly is false
- *
- * @param message
- * @param sub
- * @param purgeOnly When set to false the message will be taken by the given Subscription.
- *
- * @return if the msg should be purged
- *
- * @throws AMQException
- */
- private boolean purgeMessage(QueueEntry message, Subscription sub, boolean purgeOnly) throws AMQException
- {
- //Original.. complicated while loop control
-// (message != null
-// && (
-// ((sub != null && !sub.isBrowser()) || message.isTaken(_queue))
-// || sub == null)
-// && message.taken(_queue, sub));
-
- boolean purge = false;
-
- // if the message is null then don't purge as we have no messagse.
- if (message != null)
- {
- // Check that the message hasn't expired.
- if (message.expired())
- {
- return true;
- }
-
- // if we have a subscriber perform message checks
- if (sub != null)
- {
- // if we have a queue browser(we don't purge) so check mark the message as taken
- purge = ((!sub.isBrowser() || message.isTaken()));
- }
- else
- {
- // if there is no subscription we are doing
- // a get or purging so mark message as taken.
- message.isTaken();
- // and then ensure that it gets purged
- purge = true;
- }
- }
-
- if (purgeOnly)
- {
- // If we are simply purging the queue don't take the message
- // just purge up to the next non-taken msg.
- return purge && message.isTaken();
- }
- else
- {
- // if we are purging then ensure we mark this message taken for the current subscriber
- // the current subscriber may be null in the case of a get or a purge but this is ok.
- return purge && message.taken(sub);
- }
- }
-
- public void sendNextMessage(Subscription sub, AMQQueue queue)
- {
-
- Queue<QueueEntry> messageQueue = sub.getNextQueue(_messages);
-
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Async sendNextMessage for sub (" + System.identityHashCode(sub) +
- ") from queue (" + System.identityHashCode(messageQueue) +
- ") AMQQueue (" + System.identityHashCode(queue) + ")");
- }
-
- if (messageQueue == null)
- {
- // There is no queue with messages currently. This is ok... just means the queue has no msgs matching selector
- if (_log.isInfoEnabled())
- {
- _log.info(debugIdentity() + sub + ": asked to send messages but has none on given queue:" + queue);
- }
- return;
- }
-
- QueueEntry entry = null;
- QueueEntry removed = null;
- try
- {
- synchronized (_queueHeadLock)
- {
- entry = getNextMessage(messageQueue, sub, false);
-
- // message will be null if we have no messages in the messageQueue.
- if (entry == null)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "No messages for Subscriber(" + System.identityHashCode(sub) + ") from queue; (" + System.identityHashCode(messageQueue) + ")");
- }
- return;
- }
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Async Delivery Message :" + entry + "(" + System.identityHashCode(entry) +
- ") by :" + System.identityHashCode(this) +
- ") to :" + System.identityHashCode(sub));
- }
-
-
- if (messageQueue == _messages)
- {
- _totalMessageSize.addAndGet(-entry.getSize());
- }
-
- sub.send(entry, _queue);
-
- //remove sent message from our queue.
- removed = messageQueue.poll();
- //If we don't remove the message from _messages
- // Otherwise the Async send will never end
- }
-
- if (removed != entry)
- {
- _log.error("Just send message:" + entry.getMessage().debugIdentity() + " BUT removed this from queue:" + removed);
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Async Delivered Message r:" + removed.getMessage().debugIdentity() + "d:" + entry +
- ") by :" + System.identityHashCode(this) +
- ") to :" + System.identityHashCode(sub));
- }
-
-
- if (messageQueue == sub.getResendQueue())
- {
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "All messages sent from resendQueue for " + sub);
- }
- if (messageQueue.isEmpty())
- {
- subscriberHasPendingResend(false, sub, null);
- //better to use the above method as this keeps all the tracking in one location.
- // _hasContent.remove(sub);
- }
-
- _extraMessages.decrementAndGet();
- }
- else if (messageQueue == sub.getPreDeliveryQueue() && !sub.isBrowser())
- {
- cleanMainQueue(sub);
- }
-
- }
- catch (AMQException e)
- {
- if (entry != null)
- {
- entry.release();
- }
- else
- {
- _log.error(debugIdentity() + "Unable to release message as it is null. " + e, e);
- }
- _log.error(debugIdentity() + "Unable to deliver message as dequeue failed: " + e, e);
- }
- }
-
- private void cleanMainQueue(Subscription sub)
- {
- try
- {
- getNextMessage(_messages, sub, true);
- }
- catch (AMQException e)
- {
- _log.warn("Problem during main queue purge:" + e.getMessage());
- }
- }
-
- /**
- * enqueues the messages in the list on the queue and all required predelivery queues
- *
- * @param storeContext
- * @param movedMessageList
- */
- public void enqueueMovedMessages(StoreContext storeContext, List<QueueEntry> movedMessageList)
- {
- _lock.lock();
- try
- {
- for (QueueEntry entry : movedMessageList)
- {
- addMessageToQueue(entry, false);
- }
-
- // enqueue on the pre delivery queues
- for (Subscription sub : _subscriptions.getSubscriptions())
- {
- for (QueueEntry entry : movedMessageList)
- {
- // Only give the message to those that want them.
- if (sub.hasInterest(entry))
- {
- sub.enqueueForPreDelivery(entry, true);
- }
- }
- }
- }
- finally
- {
- _lock.unlock();
- }
- }
-
- /**
- * Only one thread should ever execute this method concurrently, but it can do so while other threads invoke
- * deliver().
- */
- private void processQueue()
- {
- //record thread name
- if (_log.isDebugEnabled())
- {
- _processingThreadName = Thread.currentThread().getName();
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Running process Queue." + currentStatus());
- }
-
- // Continue to process delivery while we haveSubscribers and messages
- boolean hasSubscribers = _subscriptions.hasActiveSubscribers();
-
- while (hasSubscribers && hasQueuedMessages() && !_movingMessages.get())
- {
- hasSubscribers = false;
-
- for (Subscription sub : _subscriptions.getSubscriptions())
- {
- synchronized (sub.getSendLock())
- {
- if (!sub.isSuspended())
- {
- sendNextMessage(sub, _queue);
-
- hasSubscribers = true;
- }
- }
- }
- }
-
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Done process Queue." + currentStatus());
- }
-
- }
-
- public void deliver(StoreContext context, AMQShortString name, QueueEntry entry, boolean deliverFirst) throws AMQException
- {
-
- final boolean debugEnabled = _log.isDebugEnabled();
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + "deliver :first(" + deliverFirst + ") :" + entry);
- }
-
- //Check if we have someone to deliver the message to.
- _lock.lock();
- try
- {
- Subscription s = _subscriptions.nextSubscriber(entry);
-
- if (s == null || (!s.filtersMessages() && hasQueuedMessages())) //no-one can take the message right now or we're queueing
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + "Testing Message(" + entry + ") for Queued Delivery:" + currentStatus());
- }
- if (!entry.getMessage().getMessagePublishInfo().isImmediate())
- {
- addMessageToQueue(entry, deliverFirst);
-
- //release lock now message is on queue.
- _lock.unlock();
-
- //Pre Deliver to all subscriptions
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + "We have " + _subscriptions.getSubscriptions().size() +
- " subscribers to give the message to:" + currentStatus());
- }
- for (Subscription sub : _subscriptions.getSubscriptions())
- {
-
- // Only give the message to those that want them.
- if (sub.hasInterest(entry))
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + "Queuing message(" + System.identityHashCode(entry) +
- ") for PreDelivery for subscriber(" + System.identityHashCode(sub) + ")");
- }
- sub.enqueueForPreDelivery(entry, deliverFirst);
- }
- }
-
- //if we have a non-filtering subscriber but queued messages && we're not Async && we have other Active subs then something is wrong!
- if ((s != null && hasQueuedMessages()) && !isProcessingAsync() && _subscriptions.hasActiveSubscribers())
- {
- _queue.deliverAsync();
- }
-
- }
- }
- else
- {
-
- if (s.filtersMessages())
- {
- if (s.getPreDeliveryQueue().size() > 0)
- {
- _log.error("Direct delivery from PDQ with queued msgs:" + s.getPreDeliveryQueue().size());
- }
- }
- else if (_messages.size() > 0)
- {
- _log.error("Direct delivery from MainQueue queued msgs:" + _messages.size());
- }
-
- //release lock now
- _lock.unlock();
- synchronized (s.getSendLock())
- {
- if (!s.isSuspended())
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + "Delivering Message:" + entry.getMessage().debugIdentity() + " to(" +
- System.identityHashCode(s) + ") :" + s);
- }
-
- if (entry.taken(s))
- {
- //Message has been delivered so don't redeliver.
- // This can currently occur because of the recursive call below
- // During unit tests the send can occur
- // client then rejects
- // this reject then releases the message by the time the
- // if(!msg.isTaken()) call is made below
- // the message has been released so that thread loops to send the message again
- // of course by the time it gets back to here. the thread that released the
- // message is now ready to send it. Here is a sample trace for reference
-//1192627162613:Thread[pool-917-thread-4,5,main]:CSDM:delivery:(true)message:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=null}:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=41, session=anonymous(5050419), resendQueue=false]
-//1192627162613:Thread[pool-917-thread-4,5,main]:Msg:taken:Q:Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=41, session=anonymous(5050419), resendQueue=false]:this:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=null}
-//1192627162613:Thread[pool-917-thread-4,5,main]:28398657 Sent :dt:214 msg:(HC:5529738 ID:145 Ref:1)
-//1192627162613:Thread[pool-917-thread-2,5,main]:Reject message by:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=41, session=anonymous(5050419), resendQueue=false]
-//1192627162613:Thread[pool-917-thread-2,5,main]:Releasing Message:(HC:5529738 ID:145 Ref:1)
-//1192627162613:Thread[pool-917-thread-2,5,main]:Msg:Release:Q:Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326:This:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=41, session=anonymous(5050419), resendQueue=false]}
-//1192627162613:Thread[pool-917-thread-2,5,main]:CSDM:delivery:(true)message:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=null}:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=33, session=anonymous(26960027), resendQueue=false]
-//1192627162629:Thread[pool-917-thread-4,5,main]:CSDM:suspended: Message((HC:5529738 ID:145 Ref:1)) has not been taken so recursing!: Subscriber:28398657
-//1192627162629:Thread[pool-917-thread-4,5,main]:CSDM:delivery:(true)message:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=null}:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=33, session=anonymous(26960027), resendQueue=false]
-//1192627162629:Thread[pool-917-thread-2,5,main]:Msg:taken:Q:Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=33, session=anonymous(26960027), resendQueue=false]:this:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=false} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=null}
-//1192627162629:Thread[pool-917-thread-2,5,main]:25386607 Sent :dt:172 msg:(HC:5529738 ID:145 Ref:1)
-//1192627162629:Thread[pool-917-thread-4,5,main]:Msg:taken:Q:Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326:sub:[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=33, session=anonymous(26960027), resendQueue=false]:this:Message[(HC:5529738 ID:145 Ref:1)]: 145; ref count: 1; taken for queues: {Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=true} by Subs:{Queue(queue-596fb10e-2968-4e51-a751-1e6643bf9dd6)@16017326=[channel=Channel: id 1, transaction mode: true, prefetch marks: 2500/5000, consumerTag=33, session=anonymous(26960027), resendQueue=false]}
- // Note: In the last request to take the message from thread 4,5 the message has been
- // taken by the previous call done by thread 2,5
-
-
- return;
- }
- //Deliver the message
- s.send(entry, _queue);
- }
- else
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + " Subscription(" + System.identityHashCode(s) + ") became " +
- "suspended between nextSubscriber and send for message:" + entry.getMessage().debugIdentity());
- }
- }
- }
-
- //
- // Why do we do this? What was the reasoning? We should have a better approach
- // than recursion and rejecting if someone else sends it before we do.
- //
- if (!entry.isTaken())
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + " Message(" + entry.getMessage().debugIdentity() + ") has not been taken so recursing!:" +
- " Subscriber:" + System.identityHashCode(s));
- }
-
- deliver(context, name, entry, deliverFirst);
- }
- else
- {
- if (debugEnabled)
- {
- _log.debug(debugIdentity() + " Message(" + entry.toString() +
- ") has been taken so disregarding deliver request to Subscriber:" +
- System.identityHashCode(s));
- }
- }
- }
-
- }
- finally
- {
- //ensure lock is released
- if (_lock.isHeldByCurrentThread())
- {
- _lock.unlock();
- }
- }
- }
-
- private final String id = "(" + String.valueOf(System.identityHashCode(this)) + ")";
-
- private String debugIdentity()
- {
- return id;
- }
-
- final Runner _asyncDelivery = new Runner();
-
- private class Runner implements Runnable
- {
- public void run()
- {
- String startName = Thread.currentThread().getName();
- Thread.currentThread().setName("CSDM-AsyncDelivery:" + startName);
- boolean running = true;
- while (running && !_movingMessages.get())
- {
- processQueue();
-
- //Check that messages have not been added since we did our last peek();
- // Synchronize with the thread that adds to the queue.
- // If the queue is still empty then we can exit
- synchronized (_asyncDelivery)
- {
- if (!(hasQueuedMessages() && _subscriptions.hasActiveSubscribers()))
- {
- running = false;
- _processing.set(false);
- }
- }
- }
- Thread.currentThread().setName(startName);
- }
- }
-
- public void processAsync(Executor executor)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Processing Async." + currentStatus());
- }
-
- synchronized (_asyncDelivery)
- {
- if (hasQueuedMessages() && _subscriptions.hasActiveSubscribers())
- {
- //are we already running? if so, don't re-run
- if (_processing.compareAndSet(false, true))
- {
- if (_log.isDebugEnabled())
- {
- _log.debug(debugIdentity() + "Executing Async process.");
- }
- executor.execute(_asyncDelivery);
- }
- }
- }
- }
-
- private String currentStatus()
- {
- return " Queued:" + (_messages.isEmpty() ? "Empty " : "Contains(H:M)") +
- "(" + ((ConcurrentLinkedMessageQueueAtomicSize) _messages).headSize() +
- ":" + (_messages.size() - ((ConcurrentLinkedMessageQueueAtomicSize) _messages).headSize()) + ") " +
- " Extra: " + (_hasContent.isEmpty() ? "Empty " : "Contains") +
- "(" + _hasContent.size() + ":" + _extraMessages.get() + ") " +
- " Active:" + _subscriptions.hasActiveSubscribers() +
- " Processing:" + (_processing.get() ? " true : Processing Thread: " + _processingThreadName : " false");
- }
-
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/DeliveryManager.java b/java/broker/src/main/java/org/apache/qpid/server/queue/DeliveryManager.java
deleted file mode 100644
index 1568f58e2e..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/DeliveryManager.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.StoreContext;
-
-interface DeliveryManager
-{
- /**
- * Determines whether there are queued messages. Sets _queueing to false if there are no queued messages. This needs
- * to be atomic.
- *
- * @return true if there are queued messages
- */
- boolean hasQueuedMessages();
-
- /**
- * This method should not be used to determin if there are messages in the queue.
- *
- * @return int The number of messages in the queue
- *
- * @use hasQueuedMessages() for all controls relating to having messages on the queue.
- */
- int getQueueMessageCount();
-
- /**
- * Requests that the delivery manager start processing the queue asynchronously if there is work that can be done
- * (i.e. there are messages queued up and subscribers that can receive them. <p/> This should be called when
- * subscribers are added, but only after the consume-ok message has been returned as message delivery may start
- * immediately. It should also be called after unsuspending a client. <p/>
- *
- * @param executor the executor on which the delivery should take place
- */
- void processAsync(Executor executor);
-
- /**
- * Handles message delivery. The delivery manager is always in one of two modes; it is either queueing messages for
- * asynchronous delivery or delivering directly.
- *
- * @param storeContext
- * @param name the name of the entity on whose behalf we are delivering the message
- * @param entry the message to deliver
- * @param deliverFirst
- *
- * @throws org.apache.qpid.server.queue.FailedDequeueException
- * if the message could not be dequeued
- */
- void deliver(StoreContext storeContext, AMQShortString name, QueueEntry entry, boolean deliverFirst) throws FailedDequeueException, AMQException;
-
- void removeAMessageFromTop(StoreContext storeContext, AMQQueue queue) throws AMQException;
-
- long clearAllMessages(StoreContext storeContext) throws AMQException;
-
- void startMovingMessages();
-
- void enqueueMovedMessages(StoreContext context, List<QueueEntry> messageList);
-
- void stopMovingMessages();
-
- void removeMovedMessages(List<QueueEntry> messageListToRemove);
-
- List<QueueEntry> getMessages();
-
- List<QueueEntry> getMessages(long fromMessageId, long toMessageId);
-
- void populatePreDeliveryQueue(Subscription subscription);
-
- boolean performGet(AMQProtocolSession session, AMQChannel channel, boolean acks) throws AMQException;
-
- long getTotalMessageSize();
-
- long getOldestMessageArrival();
-
- void subscriberHasPendingResend(boolean hasContent, Subscription subscription, QueueEntry msg);
-
- void removeExpired() throws AMQException;
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java
new file mode 100644
index 0000000000..a2fcab9e73
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+
+public class ExchangeBinding
+{
+ private final Exchange _exchange;
+ private final AMQShortString _routingKey;
+ private final FieldTable _arguments;
+
+ private static final FieldTable EMPTY_ARGUMENTS = new FieldTable();
+
+ ExchangeBinding(AMQShortString routingKey, Exchange exchange)
+ {
+ this(routingKey, exchange, EMPTY_ARGUMENTS);
+ }
+
+ ExchangeBinding(AMQShortString routingKey, Exchange exchange, FieldTable arguments)
+ {
+ _routingKey = routingKey == null ? AMQShortString.EMPTY_STRING : routingKey;
+ _exchange = exchange;
+ _arguments = arguments == null ? EMPTY_ARGUMENTS : arguments;
+ }
+
+ void unbind(AMQQueue queue) throws AMQException
+ {
+ _exchange.deregisterQueue(_routingKey, queue, _arguments);
+ }
+
+ public Exchange getExchange()
+ {
+ return _exchange;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return _routingKey;
+ }
+
+ public FieldTable getArguments()
+ {
+ return _arguments;
+ }
+
+ public int hashCode()
+ {
+ return (_exchange == null ? 0 : _exchange.hashCode())
+ + (_routingKey == null ? 0 : _routingKey.hashCode());
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof ExchangeBinding))
+ {
+ return false;
+ }
+ ExchangeBinding eb = (ExchangeBinding) o;
+ return _exchange.equals(eb._exchange)
+ && _routingKey.equals(eb._routingKey);
+ }
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java
index e6377b33da..fb839c1783 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java
@@ -36,59 +36,6 @@ import org.apache.qpid.server.exchange.Exchange;
*/
class ExchangeBindings
{
- private static final FieldTable EMPTY_ARGUMENTS = new FieldTable();
-
- static class ExchangeBinding
- {
- private final Exchange _exchange;
- private final AMQShortString _routingKey;
- private final FieldTable _arguments;
-
- ExchangeBinding(AMQShortString routingKey, Exchange exchange)
- {
- this(routingKey, exchange, EMPTY_ARGUMENTS);
- }
-
- ExchangeBinding(AMQShortString routingKey, Exchange exchange, FieldTable arguments)
- {
- _routingKey = routingKey == null ? AMQShortString.EMPTY_STRING : routingKey;
- _exchange = exchange;
- _arguments = arguments == null ? EMPTY_ARGUMENTS : arguments;
- }
-
- void unbind(AMQQueue queue) throws AMQException
- {
- _exchange.deregisterQueue(_routingKey, queue, _arguments);
- }
-
- public Exchange getExchange()
- {
- return _exchange;
- }
-
- public AMQShortString getRoutingKey()
- {
- return _routingKey;
- }
-
- public int hashCode()
- {
- return (_exchange == null ? 0 : _exchange.hashCode())
- + (_routingKey == null ? 0 : _routingKey.hashCode());
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof ExchangeBinding))
- {
- return false;
- }
- ExchangeBinding eb = (ExchangeBinding) o;
- return _exchange.equals(eb._exchange)
- && _routingKey.equals(eb._routingKey);
- }
- }
-
private final List<ExchangeBinding> _bindings = new CopyOnWriteArrayList<ExchangeBinding>();
private final AMQQueue _queue;
@@ -109,9 +56,9 @@ class ExchangeBindings
}
- public void remove(AMQShortString routingKey, FieldTable arguments, Exchange exchange)
+ public boolean remove(AMQShortString routingKey, FieldTable arguments, Exchange exchange)
{
- _bindings.remove(new ExchangeBinding(routingKey, exchange, arguments));
+ return _bindings.remove(new ExchangeBinding(routingKey, exchange, arguments));
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java b/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java
new file mode 100644
index 0000000000..d38932bb61
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/Filterable.java
@@ -0,0 +1,33 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.AMQException;
+
+public interface Filterable<E extends Exception>
+{
+ ContentHeaderBody getContentHeaderBody() throws E;
+
+ boolean isPersistent() throws E;
+
+ boolean isRedelivered();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java b/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java
index 0b40f01f1a..35ad5be4e0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/InMemoryMessageHandle.java
@@ -22,11 +22,10 @@ package org.apache.qpid.server.queue;
import java.util.LinkedList;
import java.util.List;
+import java.util.Collections;
import java.util.ArrayList;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ContentChunk;
@@ -41,32 +40,40 @@ public class InMemoryMessageHandle implements AMQMessageHandle
private MessagePublishInfo _messagePublishInfo;
- private List<ContentChunk> _contentBodies = new ArrayList<ContentChunk>();
+ private List<ContentChunk> _contentBodies;
private boolean _redelivered;
private long _arrivalTime;
- public InMemoryMessageHandle()
+ private final Long _messageId;
+
+ public InMemoryMessageHandle(final Long messageId)
{
+ _messageId = messageId;
}
- public ContentHeaderBody getContentHeaderBody(StoreContext context, Long messageId) throws AMQException
+ public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException
{
return _contentHeaderBody;
}
- public int getBodyCount(StoreContext context, Long messageId)
+ public Long getMessageId()
+ {
+ return _messageId;
+ }
+
+ public int getBodyCount(StoreContext context)
{
return _contentBodies.size();
}
- public long getBodySize(StoreContext context, Long messageId) throws AMQException
+ public long getBodySize(StoreContext context) throws AMQException
{
- return getContentHeaderBody(context, messageId).bodySize;
+ return getContentHeaderBody(context).bodySize;
}
- public ContentChunk getContentChunk(StoreContext context, Long messageId, int index) throws AMQException, IllegalArgumentException
+ public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException
{
if (index > _contentBodies.size() - 1)
{
@@ -76,13 +83,28 @@ public class InMemoryMessageHandle implements AMQMessageHandle
return _contentBodies.get(index);
}
- public void addContentBodyFrame(StoreContext storeContext, Long messageId, ContentChunk contentBody, boolean isLastContentBody)
+ public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentBody, boolean isLastContentBody)
throws AMQException
{
- _contentBodies.add(contentBody);
+ if(_contentBodies == null)
+ {
+ if(isLastContentBody)
+ {
+ _contentBodies = Collections.singletonList(contentBody);
+ }
+ else
+ {
+ _contentBodies = new ArrayList<ContentChunk>();
+ _contentBodies.add(contentBody);
+ }
+ }
+ else
+ {
+ _contentBodies.add(contentBody);
+ }
}
- public MessagePublishInfo getMessagePublishInfo(StoreContext context, Long messageId) throws AMQException
+ public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException
{
return _messagePublishInfo;
}
@@ -98,12 +120,9 @@ public class InMemoryMessageHandle implements AMQMessageHandle
_redelivered = redelivered;
}
- public boolean isPersistent(StoreContext context, Long messageId) throws AMQException
+ public boolean isPersistent()
{
- //todo remove literal values to a constant file such as AMQConstants in common
- ContentHeaderBody chb = getContentHeaderBody(context, messageId);
- return chb.properties instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) chb.properties).getDeliveryMode() == 2;
+ return false;
}
/**
@@ -112,26 +131,20 @@ public class InMemoryMessageHandle implements AMQMessageHandle
* @param contentHeaderBody
* @throws AMQException
*/
- public void setPublishAndContentHeaderBody(StoreContext storeContext, Long messageId, MessagePublishInfo messagePublishInfo,
+ public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo messagePublishInfo,
ContentHeaderBody contentHeaderBody)
throws AMQException
{
_messagePublishInfo = messagePublishInfo;
_contentHeaderBody = contentHeaderBody;
+ if(contentHeaderBody.bodySize == 0)
+ {
+ _contentBodies = Collections.EMPTY_LIST;
+ }
_arrivalTime = System.currentTimeMillis();
}
- public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException
- {
- // NO OP
- }
-
- public void enqueue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException
- {
- // NO OP
- }
-
- public void dequeue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException
+ public void removeMessage(StoreContext storeContext) throws AMQException
{
// NO OP
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
new file mode 100644
index 0000000000..6287172ce8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
@@ -0,0 +1,307 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.server.txn.TransactionalContext;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.exchange.NoRouteException;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.AMQException;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class IncomingMessage implements Filterable<RuntimeException>
+{
+
+ /** Used for debugging purposes. */
+ private static final Logger _logger = Logger.getLogger(IncomingMessage.class);
+
+ private static final boolean SYNCHED_CLOCKS =
+ ApplicationRegistry.getInstance().getConfiguration().getBoolean("advanced.synced-clocks", false);
+
+ private final MessagePublishInfo _messagePublishInfo;
+ private ContentHeaderBody _contentHeaderBody;
+ private AMQMessageHandle _messageHandle;
+ private final Long _messageId;
+ private final TransactionalContext _txnContext;
+
+
+
+ /**
+ * Keeps a track of how many bytes we have received in body frames
+ */
+ private long _bodyLengthReceived = 0;
+
+ /**
+ * This is stored during routing, to know the queues to which this message should immediately be
+ * delivered. It is <b>cleared after delivery has been attempted</b>. Any persistent record of destinations is done
+ * by the message handle.
+ */
+ private ArrayList<AMQQueue> _destinationQueues;
+
+ private AMQProtocolSession _publisher;
+ private MessageStore _messageStore;
+ private long _expiration;
+
+ private Exchange _exchange;
+
+
+ public IncomingMessage(final Long messageId,
+ final MessagePublishInfo info,
+ final TransactionalContext txnContext,
+ final AMQProtocolSession publisher)
+ {
+ _messageId = messageId;
+ _messagePublishInfo = info;
+ _txnContext = txnContext;
+ _publisher = publisher;
+
+ }
+
+ public void setContentHeaderBody(final ContentHeaderBody contentHeaderBody) throws AMQException
+ {
+ _contentHeaderBody = contentHeaderBody;
+ }
+
+ public void setExpiration()
+ {
+ long expiration =
+ ((BasicContentHeaderProperties) _contentHeaderBody.properties).getExpiration();
+ long timestamp =
+ ((BasicContentHeaderProperties) _contentHeaderBody.properties).getTimestamp();
+
+ if (SYNCHED_CLOCKS)
+ {
+ _expiration = expiration;
+ }
+ else
+ {
+ // Update TTL to be in broker time.
+ if (expiration != 0L)
+ {
+ if (timestamp != 0L)
+ {
+ // todo perhaps use arrival time
+ long diff = (System.currentTimeMillis() - timestamp);
+
+ if ((diff > 1000L) || (diff < 1000L))
+ {
+ _expiration = expiration + diff;
+ }
+ }
+ }
+ }
+
+ }
+
+ public void routingComplete(final MessageStore store,
+ final MessageHandleFactory factory) throws AMQException
+ {
+
+ final boolean persistent = isPersistent();
+ _messageHandle = factory.createMessageHandle(_messageId, store, persistent);
+ if (persistent)
+ {
+ _txnContext.beginTranIfNecessary();
+ // enqueuing the messages ensure that if required the destinations are recorded to a
+ // persistent store
+
+ if(_destinationQueues != null)
+ {
+ for (int i = 0; i < _destinationQueues.size(); i++)
+ {
+ store.enqueueMessage(_txnContext.getStoreContext(),
+ _destinationQueues.get(i), _messageId);
+ }
+ }
+ }
+ }
+
+ public AMQMessage deliverToQueues()
+ throws AMQException
+ {
+
+ // we get a reference to the destination queues now so that we can clear the
+ // transient message data as quickly as possible
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Delivering message " + _messageId + " to " + _destinationQueues);
+ }
+
+ AMQMessage message = null;
+
+ try
+ {
+ // first we allow the handle to know that the message has been fully received. This is useful if it is
+ // maintaining any calculated values based on content chunks
+ _messageHandle.setPublishAndContentHeaderBody(_txnContext.getStoreContext(),
+ _messagePublishInfo, getContentHeaderBody());
+
+
+ message = new AMQMessage(_messageHandle,_txnContext.getStoreContext(), _messagePublishInfo);
+
+ message.setExpiration(_expiration);
+ message.setClientIdentifier(_publisher.getSessionIdentifier());
+
+ if ((_destinationQueues == null) || _destinationQueues.size() == 0)
+ {
+
+ if (isMandatory() || isImmediate())
+ {
+ throw new NoRouteException("No Route for message", message);
+
+ }
+ else
+ {
+ _logger.warn("MESSAGE DISCARDED: No routes for message - " + message);
+ }
+ }
+ else
+ {
+ int offset;
+ final int queueCount = _destinationQueues.size();
+ message.incrementReference(queueCount);
+ if(queueCount == 1)
+ {
+ offset = 0;
+ }
+ else
+ {
+ offset = ((int)(message.getMessageId().longValue())) % queueCount;
+ if(offset < 0)
+ {
+ offset = -offset;
+ }
+ }
+ for (int i = offset; i < queueCount; i++)
+ {
+ // normal deliver so add this message at the end.
+ _txnContext.deliver(_destinationQueues.get(i), message);
+ }
+ for (int i = 0; i < offset; i++)
+ {
+ // normal deliver so add this message at the end.
+ _txnContext.deliver(_destinationQueues.get(i), message);
+ }
+ }
+
+ // we then allow the transactional context to do something with the message content
+ // now that it has all been received, before we attempt delivery
+ _txnContext.messageFullyReceived(isPersistent());
+ message.clearStoreContext();
+ return message;
+ }
+ finally
+ {
+ // Remove refence for routing process . Reference count should now == delivered queue count
+ if(message != null) message.decrementReference(_txnContext.getStoreContext());
+ }
+
+ }
+
+ public void addContentBodyFrame(final ContentChunk contentChunk)
+ throws AMQException
+ {
+
+ _bodyLengthReceived += contentChunk.getSize();
+
+ _messageHandle.addContentBodyFrame(_txnContext.getStoreContext(), contentChunk, allContentReceived());
+
+ }
+
+ public boolean allContentReceived()
+ {
+ return (_bodyLengthReceived == getContentHeaderBody().bodySize);
+ }
+
+ public AMQShortString getExchange() throws AMQException
+ {
+ return _messagePublishInfo.getExchange();
+ }
+
+ public AMQShortString getRoutingKey() throws AMQException
+ {
+ return _messagePublishInfo.getRoutingKey();
+ }
+
+ public boolean isMandatory() throws AMQException
+ {
+ return _messagePublishInfo.isMandatory();
+ }
+
+
+ public boolean isImmediate() throws AMQException
+ {
+ return _messagePublishInfo.isImmediate();
+ }
+
+ public ContentHeaderBody getContentHeaderBody()
+ {
+ return _contentHeaderBody;
+ }
+
+
+ public boolean isPersistent()
+ {
+ //todo remove literal values to a constant file such as AMQConstants in common
+ return getContentHeaderBody().properties instanceof BasicContentHeaderProperties &&
+ ((BasicContentHeaderProperties) getContentHeaderBody().properties).getDeliveryMode() == 2;
+ }
+
+ public boolean isRedelivered()
+ {
+ return false;
+ }
+
+ public void setMessageStore(final MessageStore messageStore)
+ {
+ _messageStore = messageStore;
+ }
+
+ public Long getMessageId()
+ {
+ return _messageId;
+ }
+
+ public void setExchange(final Exchange e)
+ {
+ _exchange = e;
+ }
+
+ public void route() throws AMQException
+ {
+ _exchange.route(this);
+ }
+
+ public void enqueue(final ArrayList<AMQQueue> queues)
+ {
+ _destinationQueues = queues;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
index 061ab56024..2bc94995e9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
@@ -126,7 +126,7 @@ public interface ManagedQueue
* @param age maximum age of message.
* @throws IOException
*/
- @MBeanAttribute(name="MaximumMessageAge", description="Threshold high value for message age on thr broker")
+ @MBeanAttribute(name="MaximumMessageAge", description="Threshold high value for message age on the broker")
void setMaximumMessageAge(Long age) throws IOException;
/**
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java
index 94ab935115..0b214ca336 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/MessageHandleFactory.java
@@ -36,11 +36,11 @@ public class MessageHandleFactory
// just hardcoded for now
if (persistent)
{
- return new WeakReferenceMessageHandle(store);
+ return new WeakReferenceMessageHandle(messageId, store);
}
else
{
- return new InMemoryMessageHandle();
+ return new InMemoryMessageHandle(messageId);
}
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
index 12d6c5998a..6f9efd3200 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
@@ -1,129 +1,138 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.AMQException;
-
-public enum NotificationCheck
-{
-
- MESSAGE_COUNT_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- int msgCount;
- final long maximumMessageCount = queue.getMaximumMessageCount();
- if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
- {
- listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
- return true;
- }
- return false;
- }
- },
- MESSAGE_SIZE_ALERT(true)
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- final long maximumMessageSize = queue.getMaximumMessageSize();
- if(maximumMessageSize != 0)
- {
- // Check for threshold message size
- long messageSize = (msg == null) ? 0 : msg.getSize();
-
- if (messageSize >= maximumMessageSize)
- {
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageId() + "]");
- return true;
- }
- }
- return false;
- }
-
- },
- QUEUE_DEPTH_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- // Check for threshold queue depth in bytes
- final long maximumQueueDepth = queue.getMaximumQueueDepth();
-
- if(maximumQueueDepth != 0)
- {
- final long queueDepth = queue.getQueueDepth();
-
- if (queueDepth >= maximumQueueDepth)
- {
- listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
- return true;
- }
- }
- return false;
- }
-
- },
- MESSAGE_AGE_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
-
- final long maxMessageAge = queue.getMaximumMessageAge();
- if(maxMessageAge != 0)
- {
- final long currentTime = System.currentTimeMillis();
- final long thresholdTime = currentTime - maxMessageAge;
- final long firstArrivalTime = queue.getOldestMessageArrivalTime();
-
- if(firstArrivalTime < thresholdTime)
- {
- long oldestAge = currentTime - firstArrivalTime;
- listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
-
- return true;
- }
- }
- return false;
-
- }
-
- }
- ;
-
- private final boolean _messageSpecific;
-
- NotificationCheck()
- {
- this(false);
- }
-
- NotificationCheck(boolean messageSpecific)
- {
- _messageSpecific = messageSpecific;
- }
-
- public boolean isMessageSpecific()
- {
- return _messageSpecific;
- }
-
- abstract boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener);
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.AMQException;
+
+public enum NotificationCheck
+{
+
+ MESSAGE_COUNT_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ int msgCount;
+ final long maximumMessageCount = queue.getMaximumMessageCount();
+ if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
+ {
+ listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
+ return true;
+ }
+ return false;
+ }
+ },
+ MESSAGE_SIZE_ALERT(true)
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ final long maximumMessageSize = queue.getMaximumMessageSize();
+ if(maximumMessageSize != 0)
+ {
+ // Check for threshold message size
+ long messageSize;
+ try
+ {
+ messageSize = (msg == null) ? 0 : msg.getContentHeaderBody().bodySize;
+ }
+ catch (AMQException e)
+ {
+ messageSize = 0;
+ }
+
+
+ if (messageSize >= maximumMessageSize)
+ {
+ listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageId() + "]");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ },
+ QUEUE_DEPTH_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ // Check for threshold queue depth in bytes
+ final long maximumQueueDepth = queue.getMaximumQueueDepth();
+
+ if(maximumQueueDepth != 0)
+ {
+ final long queueDepth = queue.getQueueDepth();
+
+ if (queueDepth >= maximumQueueDepth)
+ {
+ listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ },
+ MESSAGE_AGE_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+
+ final long maxMessageAge = queue.getMaximumMessageAge();
+ if(maxMessageAge != 0)
+ {
+ final long currentTime = System.currentTimeMillis();
+ final long thresholdTime = currentTime - maxMessageAge;
+ final long firstArrivalTime = queue.getOldestMessageArrivalTime();
+
+ if(firstArrivalTime < thresholdTime)
+ {
+ long oldestAge = currentTime - firstArrivalTime;
+ listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
+
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ }
+ ;
+
+ private final boolean _messageSpecific;
+
+ NotificationCheck()
+ {
+ this(false);
+ }
+
+ NotificationCheck(boolean messageSpecific)
+ {
+ _messageSpecific = messageSpecific;
+ }
+
+ public boolean isMessageSpecific()
+ {
+ return _messageSpecific;
+ }
+
+ abstract boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener);
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
new file mode 100644
index 0000000000..fd46a8a5ff
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java
@@ -0,0 +1,169 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.CommonContentHeaderProperties;
+import org.apache.qpid.AMQException;
+
+public class PriorityQueueList implements QueueEntryList
+{
+ private final AMQQueue _queue;
+ private final QueueEntryList[] _priorityLists;
+ private final int _priorities;
+ private final int _priorityOffset;
+
+ public PriorityQueueList(AMQQueue queue, int priorities)
+ {
+ _queue = queue;
+ _priorityLists = new QueueEntryList[priorities];
+ _priorities = priorities;
+ _priorityOffset = 5-((priorities + 1)/2);
+ for(int i = 0; i < priorities; i++)
+ {
+ _priorityLists[i] = new SimpleQueueEntryList(queue);
+ }
+ }
+
+ public int getPriorities()
+ {
+ return _priorities;
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public QueueEntry add(AMQMessage message)
+ {
+ try
+ {
+ int index = ((CommonContentHeaderProperties)((message.getContentHeaderBody().properties))).getPriority() - _priorityOffset;
+ if(index >= _priorities)
+ {
+ index = _priorities-1;
+ }
+ else if(index < 0)
+ {
+ index = 0;
+ }
+ return _priorityLists[index].add(message);
+ }
+ catch (AMQException e)
+ {
+ // TODO - fix AMQ Exception
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public QueueEntry next(QueueEntry node)
+ {
+ QueueEntryImpl nodeImpl = (QueueEntryImpl)node;
+ QueueEntry next = nodeImpl.getNext();
+
+ if(next == null)
+ {
+ QueueEntryList nodeEntryList = nodeImpl.getQueueEntryList();
+ int index;
+ for(index = _priorityLists.length-1; _priorityLists[index] != nodeEntryList; index--);
+
+ while(next == null && index != 0)
+ {
+ index--;
+ next = ((QueueEntryImpl)_priorityLists[index].getHead()).getNext();
+ }
+
+ }
+ return next;
+ }
+
+ private final class PriorityQueueEntryListIterator implements QueueEntryIterator
+ {
+ private final QueueEntryIterator[] _iterators = new QueueEntryIterator[ _priorityLists.length ];
+ private QueueEntry _lastNode;
+
+ PriorityQueueEntryListIterator()
+ {
+ for(int i = 0; i < _priorityLists.length; i++)
+ {
+ _iterators[i] = _priorityLists[i].iterator();
+ }
+ _lastNode = _iterators[_iterators.length - 1].getNode();
+ }
+
+
+ public boolean atTail()
+ {
+ for(int i = 0; i < _iterators.length; i++)
+ {
+ if(!_iterators[i].atTail())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public QueueEntry getNode()
+ {
+ return _lastNode;
+ }
+
+ public boolean advance()
+ {
+ for(int i = _iterators.length-1; i >= 0; i--)
+ {
+ if(_iterators[i].advance())
+ {
+ _lastNode = _iterators[i].getNode();
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public QueueEntryIterator iterator()
+ {
+ return new PriorityQueueEntryListIterator();
+ }
+
+ public QueueEntry getHead()
+ {
+ return _priorityLists[_priorities-1].getHead();
+ }
+
+ static class Factory implements QueueEntryListFactory
+ {
+ private final int _priorities;
+
+ Factory(int priorities)
+ {
+ _priorities = priorities;
+ }
+
+ public QueueEntryList createQueueEntryList(AMQQueue queue)
+ {
+ return new PriorityQueueList(queue, _priorities);
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
index 8553db3e09..2657c459a9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
@@ -1,173 +1,184 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.store.StoreContext;
-import org.apache.log4j.Logger;
-
-import java.util.Set;
-import java.util.HashSet;
-import java.util.concurrent.atomic.AtomicReference;
-
+import org.apache.qpid.server.subscription.Subscription;
-public class QueueEntry
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public interface QueueEntry extends Comparable<QueueEntry>
{
- /**
- * Used for debugging purposes.
- */
- private static final Logger _log = Logger.getLogger(QueueEntry.class);
-
- private final AMQQueue _queue;
- private final AMQMessage _message;
- private Set<Subscription> _rejectedBy = null;
- private AtomicReference<Object> _owner = new AtomicReference<Object>();
-
-
- public QueueEntry(AMQQueue queue, AMQMessage message)
+ public static enum State
{
- _queue = queue;
- _message = message;
+ AVAILABLE,
+ ACQUIRED,
+ EXPIRED,
+ DEQUEUED,
+ DELETED
}
-
- public AMQQueue getQueue()
+ public static interface StateChangeListener
{
- return _queue;
+ public void stateChanged(QueueEntry entry, State oldSate, State newState);
}
- public AMQMessage getMessage()
+ public abstract class EntryState
{
- return _message;
- }
+ private EntryState()
+ {
+ }
- public long getSize()
- {
- return getMessage().getSize();
+ public abstract State getState();
}
- public boolean getDeliveredToConsumer()
- {
- return getMessage().getDeliveredToConsumer();
- }
- public boolean expired() throws AMQException
+ public final class AvailableState extends EntryState
{
- return getMessage().expired(_queue);
- }
- public boolean isTaken()
- {
- return _owner.get() != null;
+ public State getState()
+ {
+ return State.AVAILABLE;
+ }
}
- public boolean taken(Subscription sub)
- {
- return !(_owner.compareAndSet(null, sub == null ? this : sub));
- }
- public void setDeliveredToConsumer()
+ public final class DequeuedState extends EntryState
{
- getMessage().setDeliveredToConsumer();
- }
- public void release()
- {
- _owner.set(null);
+ public State getState()
+ {
+ return State.DEQUEUED;
+ }
}
- public String debugIdentity()
- {
- return getMessage().debugIdentity();
- }
- public void process(StoreContext storeContext, boolean deliverFirst) throws AMQException
+ public final class DeletedState extends EntryState
{
- _queue.process(storeContext, this, deliverFirst);
- }
- public void checkDeliveredToConsumer() throws NoConsumersException
- {
- _message.checkDeliveredToConsumer();
+ public State getState()
+ {
+ return State.DELETED;
+ }
}
- public void setRedelivered(boolean b)
+ public final class ExpiredState extends EntryState
{
- getMessage().setRedelivered(b);
- }
- public Subscription getDeliveredSubscription()
- {
- synchronized (this)
+ public State getState()
{
- Object owner = _owner.get();
- if (owner instanceof Subscription)
- {
- return (Subscription) owner;
- }
- else
- {
- return null;
- }
+ return State.EXPIRED;
}
}
- public void reject()
+
+ public final class NonSubscriptionAcquiredState extends EntryState
{
- reject(getDeliveredSubscription());
+ public State getState()
+ {
+ return State.ACQUIRED;
+ }
}
- public void reject(Subscription subscription)
+ public final class SubscriptionAcquiredState extends EntryState
{
- if (subscription != null)
- {
- if (_rejectedBy == null)
- {
- _rejectedBy = new HashSet<Subscription>();
- }
+ private final Subscription _subscription;
- _rejectedBy.add(subscription);
- }
- else
+ public SubscriptionAcquiredState(Subscription subscription)
{
- _log.warn("Requesting rejection by null subscriber:" + debugIdentity());
+ _subscription = subscription;
}
- }
- public boolean isRejectedBy(Subscription subscription)
- {
- boolean rejected = _rejectedBy != null;
- if (rejected) // We have subscriptions that rejected this message
+ public State getState()
{
- return _rejectedBy.contains(subscription);
+ return State.ACQUIRED;
}
- else // This messasge hasn't been rejected yet.
+
+ public Subscription getSubscription()
{
- return rejected;
+ return _subscription;
}
}
+ final static EntryState AVAILABLE_STATE = new AvailableState();
+ final static EntryState DELETED_STATE = new DeletedState();
+ final static EntryState DEQUEUED_STATE = new DequeuedState();
+ final static EntryState EXPIRED_STATE = new ExpiredState();
+ final static EntryState NON_SUBSCRIPTION_ACQUIRED_STATE = new NonSubscriptionAcquiredState();
+
+
+
+
+ AMQQueue getQueue();
+
+ AMQMessage getMessage();
+
+ long getSize();
+
+ boolean getDeliveredToConsumer();
+
+ boolean expired() throws AMQException;
+
+ boolean isAcquired();
+
+ boolean acquire();
+ boolean acquire(Subscription sub);
+
+ boolean delete();
+ boolean isDeleted();
+
+ boolean acquiredBySubscription();
+
+ void setDeliveredToSubscription();
+
+ void release();
+
+ String debugIdentity();
+
+ boolean immediateAndNotDelivered();
+
+ void setRedelivered(boolean b);
+
+ Subscription getDeliveredSubscription();
+
+ void reject();
+
+ void reject(Subscription subscription);
+
+ boolean isRejectedBy(Subscription subscription);
+
+ void requeue(StoreContext storeContext) throws AMQException;
+
+ void dequeue(final StoreContext storeContext) throws FailedDequeueException;
+
+ void dispose(final StoreContext storeContext) throws MessageCleanupException;
+
+ void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException;
+
+ boolean isQueueDeleted();
+
+ void addStateChangeListener(StateChangeListener listener);
+ boolean removeStateChangeListener(StateChangeListener listener);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
new file mode 100644
index 0000000000..dbad5438dc
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -0,0 +1,388 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.log4j.Logger;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+
+public class QueueEntryImpl implements QueueEntry
+{
+
+ /**
+ * Used for debugging purposes.
+ */
+ private static final Logger _log = Logger.getLogger(QueueEntryImpl.class);
+
+ private final SimpleQueueEntryList _queueEntryList;
+
+ private AMQMessage _message;
+
+
+ private Set<Subscription> _rejectedBy = null;
+
+ private volatile EntryState _state = AVAILABLE_STATE;
+
+ private static final
+ AtomicReferenceFieldUpdater<QueueEntryImpl, EntryState>
+ _stateUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueEntryImpl.class, EntryState.class, "_state");
+
+
+ private volatile Set<StateChangeListener> _stateChangeListeners;
+
+ private static final
+ AtomicReferenceFieldUpdater<QueueEntryImpl, Set>
+ _listenersUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueEntryImpl.class, Set.class, "_stateChangeListeners");
+
+
+ private static final
+ AtomicLongFieldUpdater<QueueEntryImpl>
+ _entryIdUpdater =
+ AtomicLongFieldUpdater.newUpdater
+ (QueueEntryImpl.class, "_entryId");
+
+
+ private volatile long _entryId;
+
+ volatile QueueEntryImpl _next;
+
+
+ QueueEntryImpl(SimpleQueueEntryList queueEntryList)
+ {
+ this(queueEntryList,null,Long.MIN_VALUE);
+ _state = DELETED_STATE;
+ }
+
+
+ public QueueEntryImpl(SimpleQueueEntryList queueEntryList, AMQMessage message, final long entryId)
+ {
+ _queueEntryList = queueEntryList;
+ _message = message;
+
+ _entryIdUpdater.set(this, entryId);
+ }
+
+ public QueueEntryImpl(SimpleQueueEntryList queueEntryList, AMQMessage message)
+ {
+ _queueEntryList = queueEntryList;
+ _message = message;
+ }
+
+ protected void setEntryId(long entryId)
+ {
+ _entryIdUpdater.set(this, entryId);
+ }
+
+ protected long getEntryId()
+ {
+ return _entryId;
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queueEntryList.getQueue();
+ }
+
+ public AMQMessage getMessage()
+ {
+ return _message;
+ }
+
+ public long getSize()
+ {
+ return getMessage().getSize();
+ }
+
+ public boolean getDeliveredToConsumer()
+ {
+ return getMessage().getDeliveredToConsumer();
+ }
+
+ public boolean expired() throws AMQException
+ {
+ return getMessage().expired(getQueue());
+ }
+
+ public boolean isAcquired()
+ {
+ return _state.getState() == State.ACQUIRED;
+ }
+
+ public boolean acquire()
+ {
+ return acquire(NON_SUBSCRIPTION_ACQUIRED_STATE);
+ }
+
+ private boolean acquire(final EntryState state)
+ {
+ boolean acquired = _stateUpdater.compareAndSet(this,AVAILABLE_STATE, state);
+ if(acquired && _stateChangeListeners != null)
+ {
+ notifyStateChange(State.AVAILABLE, State.ACQUIRED);
+ }
+
+ return acquired;
+ }
+
+ public boolean acquire(Subscription sub)
+ {
+ return acquire(sub.getOwningState());
+ }
+
+ public boolean acquiredBySubscription()
+ {
+
+ return (_state instanceof SubscriptionAcquiredState);
+ }
+
+ public void setDeliveredToSubscription()
+ {
+ getMessage().setDeliveredToConsumer();
+ }
+
+ public void release()
+ {
+ _stateUpdater.set(this,AVAILABLE_STATE);
+ }
+
+ public String debugIdentity()
+ {
+ return getMessage().debugIdentity();
+ }
+
+
+ public boolean immediateAndNotDelivered()
+ {
+ return _message.immediateAndNotDelivered();
+ }
+
+ public void setRedelivered(boolean b)
+ {
+ getMessage().setRedelivered(b);
+ }
+
+ public Subscription getDeliveredSubscription()
+ {
+ EntryState state = _state;
+ if (state instanceof SubscriptionAcquiredState)
+ {
+ return ((SubscriptionAcquiredState) state).getSubscription();
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+
+ public void reject()
+ {
+ reject(getDeliveredSubscription());
+ }
+
+ public void reject(Subscription subscription)
+ {
+ if (subscription != null)
+ {
+ if (_rejectedBy == null)
+ {
+ _rejectedBy = new HashSet<Subscription>();
+ }
+
+ _rejectedBy.add(subscription);
+ }
+ else
+ {
+ _log.warn("Requesting rejection by null subscriber:" + debugIdentity());
+ }
+ }
+
+ public boolean isRejectedBy(Subscription subscription)
+ {
+
+ if (_rejectedBy != null) // We have subscriptions that rejected this message
+ {
+ return _rejectedBy.contains(subscription);
+ }
+ else // This messasge hasn't been rejected yet.
+ {
+ return false;
+ }
+ }
+
+
+ public void requeue(final StoreContext storeContext) throws AMQException
+ {
+ getQueue().requeue(storeContext, this);
+ if(_stateChangeListeners != null)
+ {
+ notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
+ }
+ }
+
+ public void dequeue(final StoreContext storeContext) throws FailedDequeueException
+ {
+ EntryState state = _state;
+
+ if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, DEQUEUED_STATE))
+ {
+ if (state instanceof SubscriptionAcquiredState)
+ {
+ Subscription s = ((SubscriptionAcquiredState) state).getSubscription();
+ s.restoreCredit(this);
+ }
+
+ getQueue().dequeue(storeContext, this);
+ if(_stateChangeListeners != null)
+ {
+ notifyStateChange(state.getState() , QueueEntry.State.DEQUEUED);
+ }
+
+ }
+
+ }
+
+ private void notifyStateChange(final State oldState, final State newState)
+ {
+ for(StateChangeListener l : _stateChangeListeners)
+ {
+ l.stateChanged(this, oldState, newState);
+ }
+ }
+
+ public void dispose(final StoreContext storeContext) throws MessageCleanupException
+ {
+ if(delete())
+ {
+ getMessage().decrementReference(storeContext);
+ }
+ }
+
+ public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException
+ {
+ //if the queue is null then the message is waiting to be acked, but has been removed.
+ if (getQueue() != null)
+ {
+ dequeue(storeContext);
+ }
+
+ dispose(storeContext);
+ }
+
+ public boolean isQueueDeleted()
+ {
+ return getQueue().isDeleted();
+ }
+
+ public void addStateChangeListener(StateChangeListener listener)
+ {
+ Set<StateChangeListener> listeners = _stateChangeListeners;
+ if(listeners == null)
+ {
+ _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener>());
+ listeners = _stateChangeListeners;
+ }
+
+ listeners.add(listener);
+ }
+
+ public boolean removeStateChangeListener(StateChangeListener listener)
+ {
+ Set<StateChangeListener> listeners = _stateChangeListeners;
+ if(listeners != null)
+ {
+ return listeners.remove(listener);
+ }
+
+ return false;
+ }
+
+
+ public int compareTo(final QueueEntry o)
+ {
+ QueueEntryImpl other = (QueueEntryImpl)o;
+ return getEntryId() > other.getEntryId() ? 1 : getEntryId() < other.getEntryId() ? -1 : 0;
+ }
+
+ public QueueEntryImpl getNext()
+ {
+
+ QueueEntryImpl next = nextNode();
+ while(next != null && next.isDeleted())
+ {
+
+ final QueueEntryImpl newNext = next.nextNode();
+ if(newNext != null)
+ {
+ SimpleQueueEntryList._nextUpdater.compareAndSet(this,next, newNext);
+ next = nextNode();
+ }
+ else
+ {
+ next = null;
+ }
+
+ }
+ return next;
+ }
+
+ QueueEntryImpl nextNode()
+ {
+ return _next;
+ }
+
+ public boolean isDeleted()
+ {
+ return _state == DELETED_STATE;
+ }
+
+ public boolean delete()
+ {
+ EntryState state = _state;
+
+ if(state != DELETED_STATE && _stateUpdater.compareAndSet(this,state,DELETED_STATE))
+ {
+ _queueEntryList.advanceHead();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public QueueEntryList getQueueEntryList()
+ {
+ return _queueEntryList;
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java
new file mode 100644
index 0000000000..c5c115a2d1
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java
@@ -0,0 +1,30 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+public interface QueueEntryIterator
+{
+ boolean atTail();
+
+ QueueEntry getNode();
+
+ boolean advance();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
new file mode 100644
index 0000000000..313e076f61
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
@@ -0,0 +1,34 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+public interface QueueEntryList
+{
+ AMQQueue getQueue();
+
+ QueueEntry add(AMQMessage message);
+
+ QueueEntry next(QueueEntry node);
+
+ QueueEntryIterator iterator();
+
+ QueueEntry getHead();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java
new file mode 100644
index 0000000000..4dbce45f67
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java
@@ -0,0 +1,26 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+interface QueueEntryListFactory
+{
+ public QueueEntryList createQueueEntryList(AMQQueue queue);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
index f1e7c98387..959ca03c80 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
@@ -1,27 +1,27 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-
-public interface QueueNotificationListener
-{
- void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+
+public interface QueueNotificationListener
+{
+ void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
new file mode 100644
index 0000000000..b0f700d4a1
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java
@@ -0,0 +1,1638 @@
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionList;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.management.ManagedObject;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.pool.ReadWriteRunnable;
+import org.apache.qpid.pool.ReferenceCountingExecutorService;
+import org.apache.qpid.configuration.Configured;
+import org.apache.log4j.Logger;
+
+import javax.management.JMException;
+import java.util.List;
+import java.util.Set;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
+{
+ private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class);
+
+ private final AMQShortString _name;
+
+ /** null means shared */
+ private final AMQShortString _owner;
+
+ private final boolean _durable;
+
+ /** If true, this queue is deleted when the last subscriber is removed */
+ private final boolean _autoDelete;
+
+ private final VirtualHost _virtualHost;
+
+ /** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */
+ private final ExchangeBindings _bindings = new ExchangeBindings(this);
+
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+
+ private final List<Task> _deleteTaskList = new CopyOnWriteArrayList<Task>();
+
+ private final AtomicInteger _atomicQueueCount = new AtomicInteger(0);
+
+ private final AtomicLong _atomicQueueSize = new AtomicLong(0L);
+
+ private final AtomicInteger _activeSubscriberCount = new AtomicInteger();
+
+ protected final SubscriptionList _subscriptionList = new SubscriptionList(this);
+ private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead());
+
+ private volatile Subscription _exclusiveSubscriber;
+
+ protected final QueueEntryList _entries;
+
+ private final AMQQueueMBean _managedObject;
+ private final Executor _asyncDelivery;
+ private final AtomicLong _totalMessagesReceived = new AtomicLong();
+
+ /** max allowed size(KB) of a single message */
+ @Configured(path = "maximumMessageSize", defaultValue = "0")
+ public long _maximumMessageSize;
+
+ /** max allowed number of messages on a queue. */
+ @Configured(path = "maximumMessageCount", defaultValue = "0")
+ public long _maximumMessageCount;
+
+ /** max queue depth for the queue */
+ @Configured(path = "maximumQueueDepth", defaultValue = "0")
+ public long _maximumQueueDepth;
+
+ /** maximum message age before alerts occur */
+ @Configured(path = "maximumMessageAge", defaultValue = "0")
+ public long _maximumMessageAge;
+
+ /** the minimum interval between sending out consequetive alerts of the same type */
+ @Configured(path = "minimumAlertRepeatGap", defaultValue = "0")
+ public long _minimumAlertRepeatGap;
+
+ private static final int MAX_ASYNC_DELIVERIES = 10;
+
+ private final Set<NotificationCheck> _notificationChecks = EnumSet.noneOf(NotificationCheck.class);
+
+ private final AtomicLong _stateChangeCount = new AtomicLong(Long.MIN_VALUE);
+ private AtomicReference _asynchronousRunner = new AtomicReference(null);
+ private AtomicInteger _deliveredMessages = new AtomicInteger();
+
+ protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost)
+ throws AMQException
+ {
+ this(name, durable, owner, autoDelete, virtualHost, new SimpleQueueEntryList.Factory());
+ }
+
+ protected SimpleAMQQueue(AMQShortString name,
+ boolean durable,
+ AMQShortString owner,
+ boolean autoDelete,
+ VirtualHost virtualHost,
+ QueueEntryListFactory entryListFactory)
+ throws AMQException
+ {
+
+ if (name == null)
+ {
+ throw new IllegalArgumentException("Queue name must not be null");
+ }
+
+ if (virtualHost == null)
+ {
+ throw new IllegalArgumentException("Virtual Host must not be null");
+ }
+
+ _name = name;
+ _durable = durable;
+ _owner = owner;
+ _autoDelete = autoDelete;
+ _virtualHost = virtualHost;
+ _entries = entryListFactory.createQueueEntryList(this);
+
+ _asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService();
+
+ try
+ {
+ _managedObject = new AMQQueueMBean(this);
+ _managedObject.register();
+ }
+ catch (JMException e)
+ {
+ throw new AMQException("AMQQueue MBean creation has failed ", e);
+ }
+
+ // This ensure that the notification checks for the configured alerts are created.
+ setMaximumMessageAge(_maximumMessageAge);
+ setMaximumMessageCount(_maximumMessageCount);
+ setMaximumMessageSize(_maximumMessageSize);
+ setMaximumQueueDepth(_maximumQueueDepth);
+
+ }
+
+ // ------ Getters and Setters
+
+ public AMQShortString getName()
+ {
+ return _name;
+ }
+
+ public boolean isDurable()
+ {
+ return _durable;
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _autoDelete;
+ }
+
+ public AMQShortString getOwner()
+ {
+ return _owner;
+ }
+
+ public VirtualHost getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ // ------ bind and unbind
+
+ public void bind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException
+ {
+ exchange.registerQueue(routingKey, this, arguments);
+ if (isDurable() && exchange.isDurable())
+ {
+ _virtualHost.getMessageStore().bindQueue(exchange, routingKey, this, arguments);
+ }
+
+ _bindings.addBinding(routingKey, arguments, exchange);
+ }
+
+ public void unBind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException
+ {
+ exchange.deregisterQueue(routingKey, this, arguments);
+ if (isDurable() && exchange.isDurable())
+ {
+ _virtualHost.getMessageStore().unbindQueue(exchange, routingKey, this, arguments);
+ }
+
+ boolean removed = _bindings.remove(routingKey, arguments, exchange);
+ if (!removed)
+ {
+ _logger.error("Mismatch between queue bindings and exchange record of bindings");
+ }
+ }
+
+ public List<ExchangeBinding> getExchangeBindings()
+ {
+ return new ArrayList<ExchangeBinding>(_bindings.getExchangeBindings());
+ }
+
+ // ------ Manage Subscriptions
+
+ public synchronized void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException
+ {
+
+ if (isExclusiveSubscriber())
+ {
+ throw new ExistingExclusiveSubscription();
+ }
+
+ if (exclusive)
+ {
+ if (getConsumerCount() != 0)
+ {
+ throw new ExistingSubscriptionPreventsExclusive();
+ }
+ else
+ {
+ _exclusiveSubscriber = subscription;
+
+ }
+ }
+
+ _activeSubscriberCount.incrementAndGet();
+ subscription.setStateListener(this);
+ subscription.setLastSeenEntry(null, _entries.getHead());
+
+ if (!isDeleted())
+ {
+ subscription.setQueue(this);
+ _subscriptionList.add(subscription);
+ if (isDeleted())
+ {
+ subscription.queueDeleted(this);
+ }
+ }
+ else
+ {
+ // TODO
+ }
+
+ deliverAsync(subscription);
+
+ }
+
+ public synchronized void unregisterSubscription(final Subscription subscription) throws AMQException
+ {
+ if (subscription == null)
+ {
+ throw new NullPointerException("subscription argument is null");
+ }
+
+ boolean removed = _subscriptionList.remove(subscription);
+
+ if (removed)
+ {
+ subscription.close();
+ // No longer can the queue have an exclusive consumer
+ setExclusiveSubscriber(null);
+
+ QueueEntry lastSeen;
+
+ while ((lastSeen = subscription.getLastSeenEntry()) != null)
+ {
+ subscription.setLastSeenEntry(lastSeen, null);
+ }
+
+ // auto-delete queues must be deleted if there are no remaining subscribers
+
+ if (_autoDelete && getConsumerCount() == 0)
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Auto-deleteing queue:" + this);
+ }
+
+ delete();
+
+ // we need to manually fire the event to the removed subscription (which was the last one left for this
+ // queue. This is because the delete method uses the subscription set which has just been cleared
+ subscription.queueDeleted(this);
+ }
+ }
+
+ }
+
+ // ------ Enqueue / Dequeue
+
+ public QueueEntry enqueue(StoreContext storeContext, AMQMessage message) throws AMQException
+ {
+
+ incrementQueueCount();
+ incrementQueueSize(message);
+
+ _totalMessagesReceived.incrementAndGet();
+
+ QueueEntry entry;
+ Subscription exclusiveSub = _exclusiveSubscriber;
+
+ if (exclusiveSub != null)
+ {
+ exclusiveSub.getSendLock();
+
+ try
+ {
+ entry = _entries.add(message);
+
+ deliverToSubscription(exclusiveSub, entry);
+
+ // where there is more than one producer there's a reasonable chance that even though there is
+ // no "queueing" we do not deliver because we get an interleving of _entries.add and
+ // deliverToSubscription between threads. Therefore have one more try.
+ if (!(entry.isAcquired() || entry.isDeleted()))
+ {
+ deliverToSubscription(exclusiveSub, entry);
+ }
+ }
+ finally
+ {
+ exclusiveSub.releaseSendLock();
+ }
+ }
+ else
+ {
+ entry = _entries.add(message);
+ /*
+
+ iterate over subscriptions and if any is at the end of the queue and can deliver this message, then deliver the message
+
+ */
+ SubscriptionList.SubscriptionNode node = _lastSubscriptionNode.get();
+ SubscriptionList.SubscriptionNode nextNode = node.getNext();
+ if (nextNode == null)
+ {
+ nextNode = _subscriptionList.getHead().getNext();
+ }
+ while (nextNode != null)
+ {
+ if (_lastSubscriptionNode.compareAndSet(node, nextNode))
+ {
+ break;
+ }
+ else
+ {
+ node = _lastSubscriptionNode.get();
+ nextNode = node.getNext();
+ if (nextNode == null)
+ {
+ nextNode = _subscriptionList.getHead().getNext();
+ }
+ }
+ }
+
+ // always do one extra loop after we believe we've finished
+ // this catches the case where we *just* miss an update
+ int loops = 2;
+
+ while (!(entry.isAcquired() || entry.isDeleted()) && loops != 0)
+ {
+ if (nextNode == null)
+ {
+ loops--;
+ nextNode = _subscriptionList.getHead();
+ }
+ else
+ {
+ // if subscription at end, and active, offer
+ Subscription sub = nextNode.getSubscription();
+ deliverToSubscription(sub, entry);
+ }
+ nextNode = nextNode.getNext();
+
+ }
+ }
+
+ if (entry.immediateAndNotDelivered())
+ {
+ dequeue(storeContext, entry);
+ entry.dispose(storeContext);
+ }
+ else if (!(entry.isAcquired() || entry.isDeleted()))
+ {
+ checkSubscriptionsNotAheadOfDelivery(entry);
+
+ deliverAsync();
+ }
+
+ try
+ {
+ _managedObject.checkForNotification(entry.getMessage());
+ }
+ catch (JMException e)
+ {
+ throw new AMQException("Unable to get notification from manage queue: " + e, e);
+ }
+
+ return entry;
+
+ }
+
+ private void deliverToSubscription(final Subscription sub, final QueueEntry entry)
+ throws AMQException
+ {
+
+ sub.getSendLock();
+ try
+ {
+ if (subscriptionReadyAndHasInterest(sub, entry)
+ && !sub.isSuspended())
+ {
+ if (!sub.wouldSuspend(entry))
+ {
+ if (!sub.isBrowser() && !entry.acquire(sub))
+ {
+ // restore credit here that would have been taken away by wouldSuspend since we didn't manage
+ // to acquire the entry for this subscription
+ sub.restoreCredit(entry);
+ }
+ else
+ {
+
+ deliverMessage(sub, entry);
+
+ }
+ }
+ }
+ }
+ finally
+ {
+ sub.releaseSendLock();
+ }
+ }
+
+ protected void checkSubscriptionsNotAheadOfDelivery(final QueueEntry entry)
+ {
+ // This method is only required for queues which mess with ordering
+ // Simple Queues don't :-)
+ }
+
+ private void incrementQueueSize(final AMQMessage message)
+ {
+ getAtomicQueueSize().addAndGet(message.getSize());
+ }
+
+ private void incrementQueueCount()
+ {
+ getAtomicQueueCount().incrementAndGet();
+ }
+
+ private void deliverMessage(final Subscription sub, final QueueEntry entry)
+ throws AMQException
+ {
+ _deliveredMessages.incrementAndGet();
+ sub.send(entry);
+
+ }
+
+ private boolean subscriptionReadyAndHasInterest(final Subscription sub, final QueueEntry entry)
+ {
+
+ // We need to move this subscription on, past entries which are already acquired, or deleted or ones it has no
+ // interest in.
+ QueueEntry node = sub.getLastSeenEntry();
+ while (node != null && (node.isAcquired() || node.isDeleted() || !sub.hasInterest(node)))
+ {
+
+ QueueEntry newNode = _entries.next(node);
+ if (newNode != null)
+ {
+ sub.setLastSeenEntry(node, newNode);
+ node = sub.getLastSeenEntry();
+ }
+ else
+ {
+ node = null;
+ break;
+ }
+
+ }
+
+ if (node == entry)
+ {
+ // If the first entry that subscription can process is the one we are trying to deliver to it, then we are
+ // good
+ return true;
+ }
+ else
+ {
+ // Otherwise we should try to update the subscription's last seen entry to the entry we got to, providing
+ // no-one else has updated it to something furhter on in the list
+ //TODO - check
+ //updateLastSeenEntry(sub, entry);
+ return false;
+ }
+
+ }
+
+ private void updateLastSeenEntry(final Subscription sub, final QueueEntry entry)
+ {
+ QueueEntry node = sub.getLastSeenEntry();
+
+ if (node != null && entry.compareTo(node) < 0 && sub.hasInterest(entry))
+ {
+ do
+ {
+ if (sub.setLastSeenEntry(node, entry))
+ {
+ return;
+ }
+ else
+ {
+ node = sub.getLastSeenEntry();
+ }
+ }
+ while (node != null && entry.compareTo(node) < 0);
+ }
+
+ }
+
+ public void requeue(StoreContext storeContext, QueueEntry entry) throws AMQException
+ {
+
+ SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards
+ while (subscriberIter.advance())
+ {
+ Subscription sub = subscriberIter.getNode().getSubscription();
+
+ // we don't make browsers send the same stuff twice
+ if (!sub.isBrowser())
+ {
+ updateLastSeenEntry(sub, entry);
+ }
+ }
+
+ deliverAsync();
+
+ }
+
+ public void dequeue(StoreContext storeContext, QueueEntry entry) throws FailedDequeueException
+ {
+ decrementQueueCount();
+ decrementQueueSize(entry);
+ if (entry.acquiredBySubscription())
+ {
+ _deliveredMessages.decrementAndGet();
+ }
+
+ try
+ {
+ AMQMessage msg = entry.getMessage();
+ if (isDurable() && msg.isPersistent())
+ {
+ _virtualHost.getMessageStore().dequeueMessage(storeContext, this, msg.getMessageId());
+ }
+ //entry.dispose(storeContext);
+
+ }
+ catch (MessageCleanupException e)
+ {
+ // Message was dequeued, but could not then be deleted
+ // though it is no longer referenced. This should be very
+ // rare and can be detected and cleaned up on recovery or
+ // done through some form of manual intervention.
+ _logger.error(e, e);
+ }
+ catch (AMQException e)
+ {
+ throw new FailedDequeueException(_name.toString(), e);
+ }
+
+ }
+
+ private void decrementQueueSize(final QueueEntry entry)
+ {
+ getAtomicQueueSize().addAndGet(-entry.getMessage().getSize());
+ }
+
+ void decrementQueueCount()
+ {
+ getAtomicQueueCount().decrementAndGet();
+ }
+
+ public boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException
+ {
+ /* TODO : This is wrong as the subscription may be suspended, we should instead change the state of the message
+ entry to resend and move back the subscription pointer. */
+
+ subscription.getSendLock();
+ try
+ {
+ if (!subscription.isClosed())
+ {
+ deliverMessage(subscription, entry);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ finally
+ {
+ subscription.releaseSendLock();
+ }
+ }
+
+ public int getConsumerCount()
+ {
+ return _subscriptionList.size();
+ }
+
+ public int getActiveConsumerCount()
+ {
+ return _activeSubscriberCount.get();
+ }
+
+ public boolean isUnused()
+ {
+ return getConsumerCount() == 0;
+ }
+
+ public boolean isEmpty()
+ {
+ return getMessageCount() == 0;
+ }
+
+ public int getMessageCount()
+ {
+ return getAtomicQueueCount().get();
+ }
+
+ public long getQueueDepth()
+ {
+ return getAtomicQueueSize().get();
+ }
+
+ public int getUndeliveredMessageCount()
+ {
+ int count = getMessageCount() - _deliveredMessages.get();
+ if (count < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return count;
+ }
+ }
+
+ public long getReceivedMessageCount()
+ {
+ return _totalMessagesReceived.get();
+ }
+
+ public long getOldestMessageArrivalTime()
+ {
+ QueueEntry entry = getOldestQueueEntry();
+ return entry == null ? Long.MAX_VALUE : entry.getMessage().getArrivalTime();
+ }
+
+ protected QueueEntry getOldestQueueEntry()
+ {
+ return _entries.next(_entries.getHead());
+ }
+
+ public boolean isDeleted()
+ {
+ return _deleted.get();
+ }
+
+ public List<QueueEntry> getMessagesOnTheQueue()
+ {
+ ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>();
+ QueueEntryIterator queueListIterator = _entries.iterator();
+ while (queueListIterator.advance())
+ {
+ QueueEntry node = queueListIterator.getNode();
+ if (node != null && !node.isDeleted())
+ {
+ entryList.add(node);
+ }
+ }
+ return entryList;
+
+ }
+
+ public void stateChange(Subscription sub, Subscription.State oldState, Subscription.State newState)
+ {
+ if (oldState == Subscription.State.ACTIVE && newState != Subscription.State.ACTIVE)
+ {
+ _activeSubscriberCount.decrementAndGet();
+
+ }
+ else if (newState == Subscription.State.ACTIVE)
+ {
+ if (oldState != Subscription.State.ACTIVE)
+ {
+ _activeSubscriberCount.incrementAndGet();
+
+ }
+ deliverAsync(sub);
+ }
+ }
+
+ public int compareTo(final AMQQueue o)
+ {
+ return _name.compareTo(o.getName());
+ }
+
+ public AtomicInteger getAtomicQueueCount()
+ {
+ return _atomicQueueCount;
+ }
+
+ public AtomicLong getAtomicQueueSize()
+ {
+ return _atomicQueueSize;
+ }
+
+ private boolean isExclusiveSubscriber()
+ {
+ return _exclusiveSubscriber != null;
+ }
+
+ private void setExclusiveSubscriber(Subscription exclusiveSubscriber)
+ {
+ _exclusiveSubscriber = exclusiveSubscriber;
+ }
+
+ public static interface QueueEntryFilter
+ {
+ public boolean accept(QueueEntry entry);
+
+ public boolean filterComplete();
+ }
+
+ public List<QueueEntry> getMessagesOnTheQueue(final long fromMessageId, final long toMessageId)
+ {
+ return getMessagesOnTheQueue(new QueueEntryFilter()
+ {
+
+ public boolean accept(QueueEntry entry)
+ {
+ final long messageId = entry.getMessage().getMessageId();
+ return messageId >= fromMessageId && messageId <= toMessageId;
+ }
+
+ public boolean filterComplete()
+ {
+ return false;
+ }
+ });
+ }
+
+ public QueueEntry getMessageOnTheQueue(final long messageId)
+ {
+ List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ {
+ private boolean _complete;
+
+ public boolean accept(QueueEntry entry)
+ {
+ _complete = entry.getMessage().getMessageId() == messageId;
+ return _complete;
+ }
+
+ public boolean filterComplete()
+ {
+ return _complete;
+ }
+ });
+ return entries.isEmpty() ? null : entries.get(0);
+ }
+
+ public List<QueueEntry> getMessagesOnTheQueue(QueueEntryFilter filter)
+ {
+ ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>();
+ QueueEntryIterator queueListIterator = _entries.iterator();
+ while (queueListIterator.advance() && !filter.filterComplete())
+ {
+ QueueEntry node = queueListIterator.getNode();
+ if (!node.isDeleted() && filter.accept(node))
+ {
+ entryList.add(node);
+ }
+ }
+ return entryList;
+
+ }
+
+ public void moveMessagesToAnotherQueue(final long fromMessageId,
+ final long toMessageId,
+ String queueName,
+ StoreContext storeContext)
+ {
+
+ AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+ MessageStore store = getVirtualHost().getMessageStore();
+
+ List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ {
+
+ public boolean accept(QueueEntry entry)
+ {
+ final long messageId = entry.getMessage().getMessageId();
+ return (messageId >= fromMessageId)
+ && (messageId <= toMessageId)
+ && entry.acquire();
+ }
+
+ public boolean filterComplete()
+ {
+ return false;
+ }
+ });
+
+ try
+ {
+ store.beginTran(storeContext);
+
+ // Move the messages in on the message store.
+ for (QueueEntry entry : entries)
+ {
+ AMQMessage message = entry.getMessage();
+
+ if (message.isPersistent() && toQueue.isDurable())
+ {
+ store.enqueueMessage(storeContext, toQueue, message.getMessageId());
+ }
+ // dequeue does not decrement the refence count
+ entry.dequeue(storeContext);
+ }
+
+ // Commit and flush the move transcations.
+ try
+ {
+ store.commitTran(storeContext);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
+ }
+ }
+ catch (AMQException e)
+ {
+ try
+ {
+ store.abortTran(storeContext);
+ }
+ catch (AMQException rollbackEx)
+ {
+ _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx);
+ }
+ throw new RuntimeException(e);
+ }
+
+ try
+ {
+ for (QueueEntry entry : entries)
+ {
+ toQueue.enqueue(storeContext, entry.getMessage());
+
+ }
+ }
+ catch (MessageCleanupException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void copyMessagesToAnotherQueue(final long fromMessageId,
+ final long toMessageId,
+ String queueName,
+ final StoreContext storeContext)
+ {
+ AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName));
+ MessageStore store = getVirtualHost().getMessageStore();
+
+ List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter()
+ {
+
+ public boolean accept(QueueEntry entry)
+ {
+ final long messageId = entry.getMessage().getMessageId();
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId))
+ {
+ if (!entry.isDeleted())
+ {
+ return entry.getMessage().incrementReference();
+ }
+ }
+
+ return false;
+ }
+
+ public boolean filterComplete()
+ {
+ return false;
+ }
+ });
+
+ try
+ {
+ store.beginTran(storeContext);
+
+ // Move the messages in on the message store.
+ for (QueueEntry entry : entries)
+ {
+ AMQMessage message = entry.getMessage();
+
+ if (message.isReferenced() && message.isPersistent() && toQueue.isDurable())
+ {
+ store.enqueueMessage(storeContext, toQueue, message.getMessageId());
+ }
+ }
+
+ // Commit and flush the move transcations.
+ try
+ {
+ store.commitTran(storeContext);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException("Failed to commit transaction whilst moving messages on message store.", e);
+ }
+ }
+ catch (AMQException e)
+ {
+ try
+ {
+ store.abortTran(storeContext);
+ }
+ catch (AMQException rollbackEx)
+ {
+ _logger.error("Failed to rollback transaction when error occured moving messages", rollbackEx);
+ }
+ throw new RuntimeException(e);
+ }
+
+ try
+ {
+ for (QueueEntry entry : entries)
+ {
+ if (entry.getMessage().isReferenced())
+ {
+ toQueue.enqueue(storeContext, entry.getMessage());
+ }
+ }
+ }
+ catch (MessageCleanupException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void removeMessagesFromQueue(long fromMessageId, long toMessageId, StoreContext storeContext)
+ {
+
+ try
+ {
+ QueueEntryIterator queueListIterator = _entries.iterator();
+
+ while (queueListIterator.advance())
+ {
+ QueueEntry node = queueListIterator.getNode();
+
+ final long messageId = node.getMessage().getMessageId();
+
+ if ((messageId >= fromMessageId)
+ && (messageId <= toMessageId)
+ && !node.isDeleted()
+ && node.acquire())
+ {
+ node.discard(storeContext);
+ }
+
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ // ------ Management functions
+
+ public void deleteMessageFromTop(StoreContext storeContext) throws AMQException
+ {
+ QueueEntryIterator queueListIterator = _entries.iterator();
+ boolean noDeletes = true;
+
+ while (noDeletes && queueListIterator.advance())
+ {
+ QueueEntry node = queueListIterator.getNode();
+ if (!node.isDeleted() && node.acquire())
+ {
+ node.discard(storeContext);
+ noDeletes = false;
+ }
+
+ }
+ }
+
+ public long clearQueue(StoreContext storeContext) throws AMQException
+ {
+
+ QueueEntryIterator queueListIterator = _entries.iterator();
+ long count = 0;
+
+ while (queueListIterator.advance())
+ {
+ QueueEntry node = queueListIterator.getNode();
+ if (!node.isDeleted() && node.acquire())
+ {
+ node.discard(storeContext);
+ count++;
+ }
+
+ }
+ return count;
+
+ }
+
+ public void addQueueDeleteTask(final Task task)
+ {
+ _deleteTaskList.add(task);
+ }
+
+ public int delete() throws AMQException
+ {
+ if (!_deleted.getAndSet(true))
+ {
+
+ SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
+
+ while (subscriptionIter.advance())
+ {
+ Subscription s = subscriptionIter.getNode().getSubscription();
+ if (s != null)
+ {
+ s.queueDeleted(this);
+ }
+ }
+
+ _bindings.deregister();
+ _virtualHost.getQueueRegistry().unregisterQueue(_name);
+
+ _managedObject.unregister();
+ for (Task task : _deleteTaskList)
+ {
+ task.doTask(this);
+ }
+
+ _deleteTaskList.clear();
+ ReferenceCountingExecutorService.getInstance().releaseExecutorService();
+ }
+ return getMessageCount();
+
+ }
+
+ public void deliverAsync()
+ {
+ _stateChangeCount.incrementAndGet();
+
+ Runner runner = new Runner();
+
+ if (_asynchronousRunner.compareAndSet(null, runner))
+ {
+ _asyncDelivery.execute(runner);
+ }
+ }
+
+ public void deliverAsync(Subscription sub)
+ {
+ _asyncDelivery.execute(new SubFlushRunner(sub));
+ }
+
+ private class Runner implements ReadWriteRunnable
+ {
+ public void run()
+ {
+ try
+ {
+ processQueue(this);
+ }
+ catch (AMQException e)
+ {
+ _logger.error(e);
+ }
+
+ }
+
+ public boolean isRead()
+ {
+ return false;
+ }
+
+ public boolean isWrite()
+ {
+ return true;
+ }
+ }
+
+ private class SubFlushRunner implements ReadWriteRunnable
+ {
+ private final Subscription _sub;
+
+ public SubFlushRunner(Subscription sub)
+ {
+ _sub = sub;
+ }
+
+ public void run()
+ {
+ boolean complete = false;
+ try
+ {
+ complete = flushSubscription(_sub, MAX_ASYNC_DELIVERIES);
+
+ }
+ catch (AMQException e)
+ {
+ _logger.error(e);
+ }
+ if (!complete && !_sub.isSuspended())
+ {
+ _asyncDelivery.execute(this);
+ }
+
+ }
+
+ public boolean isRead()
+ {
+ return false;
+ }
+
+ public boolean isWrite()
+ {
+ return true;
+ }
+ }
+
+ public void flushSubscription(Subscription sub) throws AMQException
+ {
+ flushSubscription(sub, Long.MAX_VALUE);
+ }
+
+ public boolean flushSubscription(Subscription sub, long deliveries) throws AMQException
+ {
+ boolean atTail = false;
+ boolean advanced;
+
+ while (!sub.isSuspended() && !atTail && deliveries != 0)
+ {
+
+ advanced = false;
+ sub.getSendLock();
+ try
+ {
+ if (sub.isActive())
+ {
+ QueueEntry node = moveSubscriptionToNextNode(sub);
+ if (!(node.isAcquired() || node.isDeleted()))
+ {
+ if (!sub.isSuspended())
+ {
+ if (sub.hasInterest(node))
+ {
+ if (!sub.wouldSuspend(node))
+ {
+ if (!sub.isBrowser() && !node.acquire(sub))
+ {
+ sub.restoreCredit(node);
+
+ }
+ else
+ {
+ deliveries--;
+ deliverMessage(sub, node);
+
+ if (sub.isBrowser())
+ {
+ QueueEntry newNode = _entries.next(node);
+
+ if (newNode != null)
+ {
+ advanced = true;
+ sub.setLastSeenEntry(node, newNode);
+ node = sub.getLastSeenEntry();
+ }
+ }
+ }
+
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ // this subscription is not interested in this node so we can skip over it
+ QueueEntry newNode = _entries.next(node);
+ if (newNode != null)
+ {
+ sub.setLastSeenEntry(node, newNode);
+ }
+ }
+ }
+
+ }
+ atTail = (_entries.next(node) == null) && !advanced;
+
+ }
+ }
+ finally
+ {
+ sub.releaseSendLock();
+ }
+
+ }
+
+ // if there's (potentially) more than one subscription the others will potentially not have been advanced to the
+ // next entry they are interested in yet. This would lead to holding on to references to expired messages, etc
+ // which would give us memory "leak".
+
+ if (!isExclusiveSubscriber())
+ {
+ advanceAllSubscriptions();
+ }
+
+ if (atTail && sub.isAutoClose())
+ {
+ unregisterSubscription(sub);
+
+ ProtocolOutputConverter converter = sub.getChannel().getProtocolSession().getProtocolOutputConverter();
+ converter.confirmConsumerAutoClose(sub.getChannel().getChannelId(), sub.getConsumerTag());
+ }
+
+ return atTail;
+ }
+
+ protected void advanceAllSubscriptions() throws AMQException
+ {
+ SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
+ while (subscriberIter.advance())
+ {
+ SubscriptionList.SubscriptionNode subNode = subscriberIter.getNode();
+ Subscription sub = subNode.getSubscription();
+ moveSubscriptionToNextNode(sub);
+ }
+ }
+
+ private QueueEntry moveSubscriptionToNextNode(final Subscription sub)
+ throws AMQException
+ {
+ QueueEntry node = sub.getLastSeenEntry();
+
+ while (node != null && (node.isAcquired() || node.isDeleted() || node.expired()))
+ {
+ if (!node.isAcquired() && !node.isDeleted() && node.expired())
+ {
+ if (node.acquire())
+ {
+ final StoreContext reapingStoreContext = new StoreContext();
+ node.discard(reapingStoreContext);
+ }
+ }
+ QueueEntry newNode = _entries.next(node);
+ if (newNode != null)
+ {
+ sub.setLastSeenEntry(node, newNode);
+ node = sub.getLastSeenEntry();
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ return node;
+ }
+
+ private void processQueue(Runnable runner) throws AMQException
+ {
+ long stateChangeCount;
+ long previousStateChangeCount = Long.MIN_VALUE;
+ boolean deliveryIncomplete = true;
+
+ int extraLoops = 1;
+ int deliveries = MAX_ASYNC_DELIVERIES;
+
+ _asynchronousRunner.compareAndSet(runner, null);
+
+ while (deliveries != 0 && ((previousStateChangeCount != (stateChangeCount = _stateChangeCount.get())) || deliveryIncomplete) && _asynchronousRunner.compareAndSet(null, runner))
+ {
+ // we want to have one extra loop after every subscription has reached the point where it cannot move
+ // further, just in case the advance of one subscription in the last loop allows a different subscription to
+ // move forward in the next iteration
+
+ if (previousStateChangeCount != stateChangeCount)
+ {
+ extraLoops = 1;
+ }
+
+ previousStateChangeCount = stateChangeCount;
+ deliveryIncomplete = _subscriptionList.size() != 0;
+ boolean done = true;
+
+ SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
+ //iterate over the subscribers and try to advance their pointer
+ while (subscriptionIter.advance())
+ {
+ boolean closeConsumer = false;
+ Subscription sub = subscriptionIter.getNode().getSubscription();
+ if (sub != null)
+ {
+ sub.getSendLock();
+ try
+ {
+ QueueEntry node = moveSubscriptionToNextNode(sub);
+
+ if (node != null && sub.isActive())
+ {
+ boolean advanced = false;
+ boolean subActive = false;
+
+ if (!(node.isAcquired() || node.isDeleted()))
+ {
+ if (!sub.isSuspended())
+ {
+ subActive = true;
+ if (sub.hasInterest(node))
+ {
+ if (!sub.wouldSuspend(node))
+ {
+ if (!sub.isBrowser() && !node.acquire(sub))
+ {
+ sub.restoreCredit(node);
+
+ }
+ else
+ {
+ deliverMessage(sub, node);
+ deliveries--;
+
+ if (sub.isBrowser())
+ {
+ QueueEntry newNode = _entries.next(node);
+
+ if (newNode != null)
+ {
+ sub.setLastSeenEntry(node, newNode);
+ node = sub.getLastSeenEntry();
+ advanced = true;
+ }
+
+ }
+ }
+ done = false;
+ }
+ else // Not enough Credit for message and wouldSuspend
+ {
+ //QPID-1187 - Treat the subscription as suspended for this message
+ // and wait for the message to be removed to continue delivery.
+ subActive = false;
+
+ node.addStateChangeListener(new QueueEntryListener(sub, node));
+ }
+ }
+ else
+ {
+ // this subscription is not interested in this node so we can skip over it
+ QueueEntry newNode = _entries.next(node);
+ if (newNode != null)
+ {
+ sub.setLastSeenEntry(node, newNode);
+ }
+ }
+ }
+ }
+ final boolean atTail = (_entries.next(node) == null);
+
+ done = done && (!subActive || atTail);
+
+ closeConsumer = (atTail && !advanced && sub.isAutoClose());
+ }
+ }
+ finally
+ {
+ sub.releaseSendLock();
+ }
+
+ if (closeConsumer)
+ {
+ unregisterSubscription(sub);
+
+ ProtocolOutputConverter converter = sub.getChannel().getProtocolSession().getProtocolOutputConverter();
+ converter.confirmConsumerAutoClose(sub.getChannel().getChannelId(), sub.getConsumerTag());
+ }
+
+ }
+ if (done)
+ {
+ if (extraLoops == 0)
+ {
+ deliveryIncomplete = false;
+ }
+ else
+ {
+ extraLoops--;
+ }
+ }
+ else
+ {
+ extraLoops = 1;
+ }
+ }
+
+ _asynchronousRunner.set(null);
+ }
+
+ // If deliveries == 0 then the limitting factor was the time-slicing rather than available messages or credit
+ // therefore we should schedule this runner again (unless someone beats us to it :-) ).
+ if (deliveries == 0 && _asynchronousRunner.compareAndSet(null, runner))
+ {
+ _asyncDelivery.execute(runner);
+ }
+ }
+
+ public void removeExpiredIfNoSubscribers() throws AMQException
+ {
+
+ final StoreContext storeContext = new StoreContext();
+
+ QueueEntryIterator queueListIterator = _entries.iterator();
+
+ while (queueListIterator.advance())
+ {
+ QueueEntry node = queueListIterator.getNode();
+ if (!node.isDeleted() && node.expired() && node.acquire())
+ {
+
+ node.discard(storeContext);
+ }
+
+ }
+
+ }
+
+ public long getMinimumAlertRepeatGap()
+ {
+ return _minimumAlertRepeatGap;
+ }
+
+ public void setMinimumAlertRepeatGap(long minimumAlertRepeatGap)
+ {
+ _minimumAlertRepeatGap = minimumAlertRepeatGap;
+ }
+
+ public long getMaximumMessageAge()
+ {
+ return _maximumMessageAge;
+ }
+
+ public void setMaximumMessageAge(long maximumMessageAge)
+ {
+ _maximumMessageAge = maximumMessageAge;
+ if (maximumMessageAge == 0L)
+ {
+ _notificationChecks.remove(NotificationCheck.MESSAGE_AGE_ALERT);
+ }
+ else
+ {
+ _notificationChecks.add(NotificationCheck.MESSAGE_AGE_ALERT);
+ }
+ }
+
+ public long getMaximumMessageCount()
+ {
+ return _maximumMessageCount;
+ }
+
+ public void setMaximumMessageCount(final long maximumMessageCount)
+ {
+ _maximumMessageCount = maximumMessageCount;
+ if (maximumMessageCount == 0L)
+ {
+ _notificationChecks.remove(NotificationCheck.MESSAGE_COUNT_ALERT);
+ }
+ else
+ {
+ _notificationChecks.add(NotificationCheck.MESSAGE_COUNT_ALERT);
+ }
+
+ }
+
+ public long getMaximumQueueDepth()
+ {
+ return _maximumQueueDepth;
+ }
+
+ // Sets the queue depth, the max queue size
+ public void setMaximumQueueDepth(final long maximumQueueDepth)
+ {
+ _maximumQueueDepth = maximumQueueDepth;
+ if (maximumQueueDepth == 0L)
+ {
+ _notificationChecks.remove(NotificationCheck.QUEUE_DEPTH_ALERT);
+ }
+ else
+ {
+ _notificationChecks.add(NotificationCheck.QUEUE_DEPTH_ALERT);
+ }
+
+ }
+
+ public long getMaximumMessageSize()
+ {
+ return _maximumMessageSize;
+ }
+
+ public void setMaximumMessageSize(final long maximumMessageSize)
+ {
+ _maximumMessageSize = maximumMessageSize;
+ if (maximumMessageSize == 0L)
+ {
+ _notificationChecks.remove(NotificationCheck.MESSAGE_SIZE_ALERT);
+ }
+ else
+ {
+ _notificationChecks.add(NotificationCheck.MESSAGE_SIZE_ALERT);
+ }
+ }
+
+ public Set<NotificationCheck> getNotificationChecks()
+ {
+ return _notificationChecks;
+ }
+
+ public ManagedObject getManagedObject()
+ {
+ return _managedObject;
+ }
+
+ private final class QueueEntryListener implements QueueEntry.StateChangeListener
+ {
+ private final QueueEntry _entry;
+ private final Subscription _sub;
+
+ public QueueEntryListener(final Subscription sub, final QueueEntry entry)
+ {
+ _entry = entry;
+ _sub = sub;
+ }
+
+ public boolean equals(Object o)
+ {
+ return _entry == ((QueueEntryListener) o)._entry && _sub == ((QueueEntryListener) o)._sub;
+ }
+
+ public int hashCode()
+ {
+ return System.identityHashCode(_entry) ^ System.identityHashCode(_sub);
+ }
+
+ public void stateChanged(QueueEntry entry, QueueEntry.State oldSate, QueueEntry.State newState)
+ {
+ entry.removeStateChangeListener(this);
+ deliverAsync(_sub);
+ }
+ }
+
+ public List<Long> getMessagesOnTheQueue(int num)
+ {
+ return getMessagesOnTheQueue(num, 0);
+ }
+
+ public List<Long> getMessagesOnTheQueue(int num, int offset)
+ {
+ ArrayList<Long> ids = new ArrayList<Long>(num);
+ QueueEntryIterator it = _entries.iterator();
+ for (int i = 0; i < offset; i++)
+ {
+ it.advance();
+ }
+
+ for (int i = 0; i < num && !it.atTail(); i++)
+ {
+ it.advance();
+ ids.add(it.getNode().getMessage().getMessageId());
+ }
+ return ids;
+ }
+} \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
new file mode 100644
index 0000000000..a46c5ae2e8
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -0,0 +1,178 @@
+package org.apache.qpid.server.queue;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class SimpleQueueEntryList implements QueueEntryList
+{
+ private final QueueEntryImpl _head;
+
+ private volatile QueueEntryImpl _tail;
+
+ static final AtomicReferenceFieldUpdater<SimpleQueueEntryList, QueueEntryImpl>
+ _tailUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (SimpleQueueEntryList.class, QueueEntryImpl.class, "_tail");
+
+
+ private final AMQQueue _queue;
+
+ static final AtomicReferenceFieldUpdater<QueueEntryImpl, QueueEntryImpl>
+ _nextUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueEntryImpl.class, QueueEntryImpl.class, "_next");
+
+
+
+
+
+ public SimpleQueueEntryList(AMQQueue queue)
+ {
+ _queue = queue;
+ _head = new QueueEntryImpl(this);
+ _tail = _head;
+ }
+
+ void advanceHead()
+ {
+ QueueEntryImpl head = _head.nextNode();
+ while(head._next != null && head.isDeleted())
+ {
+
+ final QueueEntryImpl newhead = head.nextNode();
+ if(newhead != null)
+ {
+ _nextUpdater.compareAndSet(_head,head, newhead);
+ }
+ head = _head.nextNode();
+ }
+ }
+
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+
+ public QueueEntry add(AMQMessage message)
+ {
+ QueueEntryImpl node = new QueueEntryImpl(this, message);
+ for (;;)
+ {
+ QueueEntryImpl tail = _tail;
+ QueueEntryImpl next = tail.nextNode();
+ if (tail == _tail)
+ {
+ if (next == null)
+ {
+ node.setEntryId(tail.getEntryId()+1);
+ if (_nextUpdater.compareAndSet(tail, null, node))
+ {
+ _tailUpdater.compareAndSet(this, tail, node);
+
+ return node;
+ }
+ }
+ else
+ {
+ _tailUpdater.compareAndSet(this,tail, next);
+ }
+ }
+ }
+ }
+
+ public QueueEntry next(QueueEntry node)
+ {
+ return ((QueueEntryImpl)node).getNext();
+ }
+
+
+ public class QueueEntryIteratorImpl implements QueueEntryIterator
+ {
+
+ private QueueEntryImpl _lastNode;
+
+ QueueEntryIteratorImpl(QueueEntryImpl startNode)
+ {
+ _lastNode = startNode;
+ }
+
+
+ public boolean atTail()
+ {
+ return _lastNode.nextNode() == null;
+ }
+
+ public QueueEntry getNode()
+ {
+
+ return _lastNode;
+
+ }
+
+ public boolean advance()
+ {
+
+ if(!atTail())
+ {
+ QueueEntryImpl nextNode = _lastNode.nextNode();
+ while(nextNode.isDeleted() && nextNode.nextNode() != null)
+ {
+ nextNode = nextNode.nextNode();
+ }
+ _lastNode = nextNode;
+ return true;
+
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+
+ public QueueEntryIterator iterator()
+ {
+ return new QueueEntryIteratorImpl(_head);
+ }
+
+
+ public QueueEntry getHead()
+ {
+ return _head;
+ }
+
+ static class Factory implements QueueEntryListFactory
+ {
+
+ public QueueEntryList createQueueEntryList(AMQQueue queue)
+ {
+ return new SimpleQueueEntryList(queue);
+ }
+ }
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
deleted file mode 100644
index 05cd461582..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.common.AMQPFilterTypes;
-import org.apache.qpid.common.ClientProperties;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.server.filter.FilterManager;
-import org.apache.qpid.server.filter.FilterManagerFactory;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.util.ConcurrentLinkedQueueAtomicSize;
-import org.apache.qpid.util.MessageQueue;
-import org.apache.qpid.util.ConcurrentLinkedMessageQueueAtomicSize;
-
-/**
- * Encapsulation of a supscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag
- * that was given out by the broker and the channel id. <p/>
- */
-public class SubscriptionImpl implements Subscription
-{
-
- private static final Logger _suspensionlogger = Logger.getLogger("Suspension");
- private static final Logger _logger = Logger.getLogger(SubscriptionImpl.class);
-
- public final AMQChannel channel;
-
- public final AMQProtocolSession protocolSession;
-
- public final AMQShortString consumerTag;
-
- private final Object _sessionKey;
-
- private MessageQueue<QueueEntry> _messages;
-
- private Queue<QueueEntry> _resendQueue;
-
- private final boolean _noLocal;
-
- /** True if messages need to be acknowledged */
- private final boolean _acks;
- private FilterManager _filters;
- private final boolean _isBrowser;
- private final Boolean _autoClose;
- private boolean _sentClose = false;
-
- private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString();
-
- private AMQQueue _queue;
- private final AtomicBoolean _sendLock = new AtomicBoolean(false);
-
-
- public static class Factory implements SubscriptionFactory
- {
- public Subscription createSubscription(int channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, boolean acks, FieldTable filters,
- boolean noLocal, AMQQueue queue) throws AMQException
- {
- return new SubscriptionImpl(channel, protocolSession, consumerTag, acks, filters, noLocal, queue);
- }
-
- public SubscriptionImpl createSubscription(int channel, AMQProtocolSession protocolSession, AMQShortString consumerTag)
- throws AMQException
- {
- return new SubscriptionImpl(channel, protocolSession, consumerTag, false, null, false, null);
- }
- }
-
- public SubscriptionImpl(int channelId, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, boolean acks)
- throws AMQException
- {
- this(channelId, protocolSession, consumerTag, acks, null, false, null);
- }
-
- public SubscriptionImpl(int channelId, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, boolean acks, FieldTable filters,
- boolean noLocal, AMQQueue queue)
- throws AMQException
- {
- AMQChannel channel = protocolSession.getChannel(channelId);
- if (channel == null)
- {
- throw new AMQException(AMQConstant.NOT_FOUND, "channel :" + channelId + " not found in protocol session");
- }
-
- this.channel = channel;
- this.protocolSession = protocolSession;
- this.consumerTag = consumerTag;
- _sessionKey = protocolSession.getKey();
- _acks = acks;
- _noLocal = noLocal;
- _queue = queue;
-
- _filters = FilterManagerFactory.createManager(filters);
-
-
- if (_filters != null)
- {
- Object isBrowser = filters.get(AMQPFilterTypes.NO_CONSUME.getValue());
- if (isBrowser != null)
- {
- _isBrowser = (Boolean) isBrowser;
- }
- else
- {
- _isBrowser = false;
- }
- }
- else
- {
- _isBrowser = false;
- }
-
-
- if (_filters != null)
- {
- Object autoClose = filters.get(AMQPFilterTypes.AUTO_CLOSE.getValue());
- if (autoClose != null)
- {
- _autoClose = (Boolean) autoClose;
- }
- else
- {
- _autoClose = false;
- }
- }
- else
- {
- _autoClose = false;
- }
-
-
- if (filtersMessages())
- {
- _messages = new ConcurrentLinkedMessageQueueAtomicSize<QueueEntry>();
- }
- else
- {
- // Reference the DeliveryManager
- _messages = null;
- }
- }
-
-
- public SubscriptionImpl(int channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag)
- throws AMQException
- {
- this(channel, protocolSession, consumerTag, false);
- }
-
- public boolean equals(Object o)
- {
- return (o instanceof SubscriptionImpl) && equals((SubscriptionImpl) o);
- }
-
- /**
- * Equality holds if the session matches and the channel and consumer tag are the same.
- *
- * @param psc The subscriptionImpl to compare
- *
- * @return equality
- */
- private boolean equals(SubscriptionImpl psc)
- {
- return _sessionKey.equals(psc._sessionKey)
- && psc.channel == channel
- && psc.consumerTag.equals(consumerTag);
- }
-
- public int hashCode()
- {
- return _sessionKey.hashCode();
- }
-
- public String toString()
- {
- String subscriber = "[channel=" + channel +
- ", consumerTag=" + consumerTag +
- ", session=" + protocolSession.getKey() +
- ", resendQueue=" + (_resendQueue != null);
-
- if (_resendQueue != null)
- {
- subscriber += ", resendSize=" + _resendQueue.size();
- }
-
-
- return subscriber + "]";
- }
-
- /**
- * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
- * thread safe.
- *
- * @param msg The message to send
- * @param queue the Queue it has been sent from
- *
- * @throws AMQException
- */
- public void send(QueueEntry msg, AMQQueue queue) throws AMQException
- {
- if (msg != null)
- {
- if (_isBrowser)
- {
- sendToBrowser(msg, queue);
- }
- else
- {
- sendToConsumer(channel.getStoreContext(), msg, queue);
- }
- }
- else
- {
- _logger.error("Attempt to send Null message", new NullPointerException());
- }
- }
-
- private void sendToBrowser(QueueEntry msg, AMQQueue queue) throws AMQException
- {
- // We don't decrement the reference here as we don't want to consume the message
- // but we do want to send it to the client.
-
- synchronized (channel)
- {
- long deliveryTag = channel.getNextDeliveryTag();
-
- if (_sendLock.get())
- {
- _logger.error("Sending " + msg + " when subscriber(" + this + ") is closed!");
- }
-
- protocolSession.getProtocolOutputConverter().writeDeliver(msg.getMessage(), channel.getChannelId(), deliveryTag, consumerTag);
- }
- }
-
- private void sendToConsumer(StoreContext storeContext, QueueEntry entry, AMQQueue queue)
- throws AMQException
- {
- try
- { // if we do not need to wait for client acknowledgements
- // we can decrement the reference count immediately.
-
- // By doing this _before_ the send we ensure that it
- // doesn't get sent if it can't be dequeued, preventing
- // duplicate delivery on recovery.
-
- // The send may of course still fail, in which case, as
- // the message is unacked, it will be lost.
- final AMQMessage message = entry.getMessage();
-
- if (!_acks)
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("No ack mode so dequeuing message immediately: " + message.getMessageId());
- }
- queue.dequeue(storeContext, entry);
- }
-
- final ProtocolOutputConverter outputConverter = protocolSession.getProtocolOutputConverter();
- final int channelId = channel.getChannelId();
-
- synchronized (channel)
- {
- final long deliveryTag = channel.getNextDeliveryTag();
-
-
- if (_acks)
- {
- channel.addUnacknowledgedMessage(entry, deliveryTag, consumerTag);
- }
-
- outputConverter.writeDeliver(message, channelId, deliveryTag, consumerTag);
-
-
- }
- if (!_acks)
- {
- message.decrementReference(storeContext);
- }
- }
- finally
- {
- //Only set delivered if it actually was writen successfully..
- // using a try->finally would set it even if an error occured.
- // Is this what we want?
-
- entry.setDeliveredToConsumer();
- }
- }
-
- public boolean isSuspended()
- {
-// if (_suspensionlogger.isInfoEnabled())
-// {
-// if (channel.isSuspended())
-// {
-// _suspensionlogger.debug("Subscription(" + debugIdentity() + ") channel's is susupended");
-// }
-// if (_sendLock.get())
-// {
-// _suspensionlogger.debug("Subscription(" + debugIdentity() + ") has sendLock set so closing.");
-// }
-// }
- return channel.isSuspended() || _sendLock.get();
- }
-
- /**
- * Callback indicating that a queue has been deleted.
- *
- * @param queue The queue to delete
- */
- public void queueDeleted(AMQQueue queue) throws AMQException
- {
- channel.queueDeleted(queue);
- }
-
- public boolean filtersMessages()
- {
- return _filters != null || _noLocal;
- }
-
- public boolean hasInterest(QueueEntry entry)
- {
- //check that the message hasn't been rejected
- if (entry.isRejectedBy(this))
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Subscription:" + debugIdentity() + " rejected message:" + entry.debugIdentity());
- }
-// return false;
- }
-
-
-
- //todo - client id should be recoreded and this test removed but handled below
- if (_noLocal)
- {
-
- final AMQProtocolSession publisher = entry.getMessage().getPublisher();
- if(publisher != null)
-
- {
- // We don't want local messages so check to see if message is one we sent
- Object localInstance;
- Object msgInstance;
-
- if ((protocolSession.getClientProperties() != null) &&
- (localInstance = protocolSession.getClientProperties().getObject(CLIENT_PROPERTIES_INSTANCE)) != null)
- {
-
- if ((publisher.getClientProperties() != null) &&
- (msgInstance = publisher.getClientProperties().getObject(CLIENT_PROPERTIES_INSTANCE)) != null)
- {
- if (localInstance == msgInstance || localInstance.equals(msgInstance))
- {
- // if (_logger.isTraceEnabled())
- // {
- // _logger.trace("(" + debugIdentity() + ") has no interest as it is a local message(" +
- // msg.debugIdentity() + ")");
- // }
- return false;
- }
- }
- }
- else
- {
-
- localInstance = protocolSession.getClientIdentifier();
- //todo - client id should be recoreded and this test removed but handled here
-
- msgInstance = publisher.getClientIdentifier();
- if (localInstance == msgInstance || ((localInstance != null) && localInstance.equals(msgInstance)))
- {
- // if (_logger.isTraceEnabled())
- // {
- // _logger.trace("(" + debugIdentity() + ") has no interest as it is a local message(" +
- // msg.debugIdentity() + ")");
- // }
- return false;
- }
- }
-
- }
- }
-
-
- return checkFilters(entry);
-
- }
-
- private String id = String.valueOf(System.identityHashCode(this));
-
- private String debugIdentity()
- {
- return id;
- }
-
- private boolean checkFilters(QueueEntry msg)
- {
- return (_filters == null) || _filters.allAllow(msg.getMessage());
- }
-
- public Queue<QueueEntry> getPreDeliveryQueue()
- {
- return _messages;
- }
-
- public void enqueueForPreDelivery(QueueEntry msg, boolean deliverFirst)
- {
- if (_messages != null)
- {
- if (deliverFirst)
- {
- _messages.pushHead(msg);
- }
- else
- {
- _messages.offer(msg);
- }
- }
- }
-
- private boolean isAutoClose()
- {
- return _autoClose;
- }
-
- public void close()
- {
- boolean closed = false;
- synchronized (_sendLock)
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Setting SendLock true:" + debugIdentity());
- }
-
- closed = _sendLock.getAndSet(true);
- }
-
- if (closed)
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Called close() on a closed subscription");
- }
-
- return;
- }
-
- if (_logger.isInfoEnabled())
- {
- _logger.info("Closing subscription (" + debugIdentity() + "):" + this);
- }
-
- if (_resendQueue != null && !_resendQueue.isEmpty())
- {
- if (_logger.isInfoEnabled())
- {
- _logger.info("Requeuing closing subscription (" + debugIdentity() + "):" + this);
- }
- requeue();
- }
-
- //remove references in PDQ
- if (_messages != null)
- {
- if (_logger.isInfoEnabled())
- {
- _logger.info("Clearing PDQ (" + debugIdentity() + "):" + this);
- }
-
- _messages.clear();
- }
- }
-
- private void autoclose()
- {
- close();
-
- if (_autoClose && !_sentClose)
- {
- _logger.info("Closing autoclose subscription (" + debugIdentity() + "):" + this);
-
- boolean unregisteredOK = false;
- try
- {
- unregisteredOK = channel.unsubscribeConsumer(protocolSession, consumerTag);
- }
- catch (AMQException e)
- {
- // Occurs if we cannot find the subscriber in the channel with protocolSession and consumerTag.
- _logger.info("Unable to UnsubscribeConsumer :" + consumerTag +" so not going to send CancelOK.");
- }
-
- if (unregisteredOK)
- {
- ProtocolOutputConverter converter = protocolSession.getProtocolOutputConverter();
- converter.confirmConsumerAutoClose(channel.getChannelId(), consumerTag);
- _sentClose = true;
- }
-
- }
- }
-
- private void requeue()
- {
- if (_queue != null)
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Requeuing :" + _resendQueue.size() + " messages");
- }
-
- while (!_resendQueue.isEmpty())
- {
- QueueEntry resent = _resendQueue.poll();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Removed for resending:" + resent.debugIdentity());
- }
-
- resent.release();
- _queue.subscriberHasPendingResend(false, this, resent);
-
- try
- {
- channel.getTransactionalContext().deliver(resent, true);
- }
- catch (AMQException e)
- {
- _logger.error("MESSAGE LOSS : Unable to re-deliver messages", e);
- }
- }
-
- if (!_resendQueue.isEmpty())
- {
- _logger.error("[MESSAGES LOST]Unable to re-deliver messages as queue is null.");
- }
-
- _queue.subscriberHasPendingResend(false, this, null);
- }
- else
- {
- if (!_resendQueue.isEmpty())
- {
- _logger.error("Unable to re-deliver messages as queue is null.");
- }
- }
-
- // Clear the messages
- _resendQueue = null;
- }
-
-
- public boolean isClosed()
- {
- return _sendLock.get(); // This rather than _close is used to signify the subscriber is now closed.
- }
-
- public boolean isBrowser()
- {
- return _isBrowser;
- }
-
- public boolean wouldSuspend(QueueEntry msg)
- {
- return _acks && channel.wouldSuspend(msg.getMessage());
- }
-
- public Queue<QueueEntry> getResendQueue()
- {
- if (_resendQueue == null)
- {
- _resendQueue = new ConcurrentLinkedQueueAtomicSize<QueueEntry>();
- }
- return _resendQueue;
- }
-
-
- public Queue<QueueEntry> getNextQueue(Queue<QueueEntry> messages)
- {
- if (_resendQueue != null && !_resendQueue.isEmpty())
- {
- return _resendQueue;
- }
-
- if (filtersMessages())
- {
- if (isAutoClose())
- {
- if (_messages.isEmpty())
- {
- autoclose();
- return null;
- }
- }
- return _messages;
- }
- else // we want the DM queue
- {
- return messages;
- }
- }
-
- public void addToResendQueue(QueueEntry msg)
- {
- // add to our resend queue
- getResendQueue().add(msg);
-
- // Mark Queue has having content.
- if (_queue == null)
- {
- _logger.error("Queue is null won't be able to resend messages");
- }
- else
- {
- _queue.subscriberHasPendingResend(true, this, msg);
- }
- }
-
- public Object getSendLock()
- {
- return _sendLock;
- }
-
- public AMQChannel getChannel()
- {
- return channel;
- }
-
- public void start()
- {
- //Check to see if we need to autoclose
- if (filtersMessages())
- {
- if (isAutoClose())
- {
- if (_messages.isEmpty())
- {
- autoclose();
- }
- }
- }
- }
-
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionManager.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionManager.java
deleted file mode 100644
index bc17bcca9c..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionManager.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.util.List;
-
-/**
- * Abstraction of actor that will determine the subscriber to whom
- * a message will be sent.
- */
-public interface SubscriptionManager
-{
- public List<Subscription> getSubscriptions();
- public boolean hasActiveSubscribers();
- public Subscription nextSubscriber(QueueEntry entry);
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java
deleted file mode 100644
index 882efd380d..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import java.util.List;
-import java.util.ListIterator;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-
-/** Holds a set of subscriptions for a queue and manages the round robin-ing of deliver etc. */
-class SubscriptionSet implements WeightedSubscriptionManager
-{
- private static final Logger _log = Logger.getLogger(SubscriptionSet.class);
-
- /** List of registered subscribers */
- private List<Subscription> _subscriptions = new CopyOnWriteArrayList<Subscription>();
-
- /** Used to control the round robin delivery of content */
- private int _currentSubscriber;
-
- private final Object _changeLock = new Object();
- private volatile boolean _exclusive;
-
-
- /** Accessor for unit tests. */
- int getCurrentSubscriber()
- {
- return _currentSubscriber;
- }
-
- public void addSubscriber(Subscription subscription)
- {
- synchronized (_changeLock)
- {
- _subscriptions.add(subscription);
- }
- }
-
- /**
- * Remove the subscription, returning it if it was found
- *
- * @param subscription
- *
- * @return null if no match was found
- */
- public Subscription removeSubscriber(Subscription subscription)
- {
- // TODO: possibly need O(1) operation here.
-
- Subscription sub = null;
- synchronized (_changeLock)
- {
- int subIndex = _subscriptions.indexOf(subscription);
-
- if (subIndex != -1)
- {
- //we can't just return the passed in subscription as it is a new object
- // and doesn't contain the stored state we need.
- //NOTE while this may be removed now anyone with an iterator will still have it in the list!!
- sub = _subscriptions.remove(subIndex);
- }
- else
- {
- _log.error("Unable to remove from index(" + subIndex + ")subscription:" + subscription);
- }
- }
- if (sub != null)
- {
- return sub;
- }
- else
- {
- debugDumpSubscription(subscription);
- return null;
- }
- }
-
- private void debugDumpSubscription(Subscription subscription)
- {
- if (_log.isDebugEnabled())
- {
- _log.debug("Subscription " + subscription + " not found. Dumping subscriptions:");
- for (Subscription s : _subscriptions)
- {
- _log.debug("Subscription: " + s);
- }
- _log.debug("Subscription dump complete");
- }
- }
-
- /**
- * Return the next unsuspended subscription or null if not found. <p/> Performance note: This method can scan all
- * items twice when looking for a subscription that is not suspended. The worst case occcurs when all subscriptions
- * are suspended. However, it is does this without synchronisation and subscriptions may be added and removed
- * concurrently. Also note that because of race conditions and when subscriptions are removed between calls to
- * nextSubscriber, the IndexOutOfBoundsException also causes the scan to start at the beginning.
- */
- public Subscription nextSubscriber(QueueEntry msg)
- {
-
-
- try
- {
- final Subscription result = nextSubscriberImpl(msg);
- if (result == null)
- {
- _currentSubscriber = 0;
- return nextSubscriberImpl(msg);
- }
- else
- {
- return result;
- }
- }
- catch (IndexOutOfBoundsException e)
- {
- _currentSubscriber = 0;
- return nextSubscriber(msg);
- }
- }
-
- private Subscription nextSubscriberImpl(QueueEntry msg)
- {
- if(_exclusive)
- {
- try
- {
- Subscription subscription = _subscriptions.get(0);
- subscriberScanned();
-
- if (!(subscription.isSuspended() || subscription.wouldSuspend(msg)))
- {
- if (subscription.hasInterest(msg))
- {
- // if the queue is not empty then this client is ready to receive a message.
- //FIXME the queue could be full of sent messages.
- // Either need to clean all PDQs after sending a message
- // OR have a clean up thread that runs the PDQs expunging the messages.
- if (!subscription.filtersMessages() || subscription.getPreDeliveryQueue().isEmpty())
- {
- return subscription;
- }
- }
- }
- }
- catch(IndexOutOfBoundsException e)
- {
- }
- return null;
- }
- else
- {
- if (_subscriptions.isEmpty())
- {
- return null;
- }
- final ListIterator<Subscription> iterator = _subscriptions.listIterator(_currentSubscriber);
- while (iterator.hasNext())
- {
- Subscription subscription = iterator.next();
- ++_currentSubscriber;
- subscriberScanned();
-
- if (!(subscription.isSuspended() || subscription.wouldSuspend(msg)))
- {
- if (subscription.hasInterest(msg))
- {
- // if the queue is not empty then this client is ready to receive a message.
- //FIXME the queue could be full of sent messages.
- // Either need to clean all PDQs after sending a message
- // OR have a clean up thread that runs the PDQs expunging the messages.
- if (!subscription.filtersMessages() || subscription.getPreDeliveryQueue().isEmpty())
- {
- return subscription;
- }
- }
- }
- }
-
- return null;
- }
- }
-
- /** Overridden in test classes. */
- protected void subscriberScanned()
- {
- }
-
- public boolean isEmpty()
- {
- return _subscriptions.isEmpty();
- }
-
- public List<Subscription> getSubscriptions()
- {
- return _subscriptions;
- }
-
- public boolean hasActiveSubscribers()
- {
- for (Subscription s : _subscriptions)
- {
- if (!s.isSuspended())
- {
- return true;
- }
- }
- return false;
- }
-
- public int getWeight()
- {
- int count = 0;
- for (Subscription s : _subscriptions)
- {
- if (!s.isSuspended())
- {
- count++;
- }
- }
- return count;
- }
-
- /**
- * Notification that a queue has been deleted. This is called so that the subscription can inform the channel, which
- * in turn can update its list of unacknowledged messages.
- *
- * @param queue
- */
- public void queueDeleted(AMQQueue queue) throws AMQException
- {
- for (Subscription s : _subscriptions)
- {
- s.queueDeleted(queue);
- }
- }
-
- int size()
- {
- return _subscriptions.size();
- }
-
-
- public Object getChangeLock()
- {
- return _changeLock;
- }
-
- public void setExclusive(final boolean exclusive)
- {
- _exclusive = exclusive;
- }
-
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java b/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java
index 373a64e2eb..3ed8b0e55c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/WeakReferenceMessageHandle.java
@@ -26,7 +26,6 @@ import java.util.LinkedList;
import java.util.List;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ContentChunk;
@@ -48,29 +47,35 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
private final MessageStore _messageStore;
+ private final Long _messageId;
private long _arrivalTime;
-
- public WeakReferenceMessageHandle(MessageStore messageStore)
+ public WeakReferenceMessageHandle(final Long messageId, MessageStore messageStore)
{
+ _messageId = messageId;
_messageStore = messageStore;
}
- public ContentHeaderBody getContentHeaderBody(StoreContext context, Long messageId) throws AMQException
+ public ContentHeaderBody getContentHeaderBody(StoreContext context) throws AMQException
{
ContentHeaderBody chb = (_contentHeaderBody != null ? _contentHeaderBody.get() : null);
if (chb == null)
{
- MessageMetaData mmd = loadMessageMetaData(context, messageId);
+ MessageMetaData mmd = loadMessageMetaData(context);
chb = mmd.getContentHeaderBody();
}
return chb;
}
- private MessageMetaData loadMessageMetaData(StoreContext context, Long messageId)
+ public Long getMessageId()
+ {
+ return _messageId;
+ }
+
+ private MessageMetaData loadMessageMetaData(StoreContext context)
throws AMQException
{
- MessageMetaData mmd = _messageStore.getMessageMetaData(context, messageId);
+ MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId);
populateFromMessageMetaData(mmd);
return mmd;
}
@@ -82,11 +87,11 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
_messagePublishInfo = new WeakReference<MessagePublishInfo>(mmd.getMessagePublishInfo());
}
- public int getBodyCount(StoreContext context, Long messageId) throws AMQException
+ public int getBodyCount(StoreContext context) throws AMQException
{
if (_contentBodies == null)
{
- MessageMetaData mmd = _messageStore.getMessageMetaData(context, messageId);
+ MessageMetaData mmd = _messageStore.getMessageMetaData(context, _messageId);
int chunkCount = mmd.getContentChunkCount();
_contentBodies = new ArrayList<WeakReference<ContentChunk>>(chunkCount);
for (int i = 0; i < chunkCount; i++)
@@ -97,12 +102,12 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
return _contentBodies.size();
}
- public long getBodySize(StoreContext context, Long messageId) throws AMQException
+ public long getBodySize(StoreContext context) throws AMQException
{
- return getContentHeaderBody(context, messageId).bodySize;
+ return getContentHeaderBody(context).bodySize;
}
- public ContentChunk getContentChunk(StoreContext context, Long messageId, int index) throws AMQException, IllegalArgumentException
+ public ContentChunk getContentChunk(StoreContext context, int index) throws AMQException, IllegalArgumentException
{
if (index > _contentBodies.size() - 1)
{
@@ -113,7 +118,7 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
ContentChunk cb = wr.get();
if (cb == null)
{
- cb = _messageStore.getContentBodyChunk(context, messageId, index);
+ cb = _messageStore.getContentBodyChunk(context, _messageId, index);
_contentBodies.set(index, new WeakReference<ContentChunk>(cb));
}
return cb;
@@ -123,12 +128,11 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
* Content bodies are set <i>before</i> the publish and header frames
*
* @param storeContext
- * @param messageId
* @param contentChunk
* @param isLastContentBody
* @throws AMQException
*/
- public void addContentBodyFrame(StoreContext storeContext, Long messageId, ContentChunk contentChunk, boolean isLastContentBody) throws AMQException
+ public void addContentBodyFrame(StoreContext storeContext, ContentChunk contentChunk, boolean isLastContentBody) throws AMQException
{
if (_contentBodies == null && isLastContentBody)
{
@@ -142,16 +146,16 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
}
}
_contentBodies.add(new WeakReference<ContentChunk>(contentChunk));
- _messageStore.storeContentBodyChunk(storeContext, messageId, _contentBodies.size() - 1,
+ _messageStore.storeContentBodyChunk(storeContext, _messageId, _contentBodies.size() - 1,
contentChunk, isLastContentBody);
}
- public MessagePublishInfo getMessagePublishInfo(StoreContext context, Long messageId) throws AMQException
+ public MessagePublishInfo getMessagePublishInfo(StoreContext context) throws AMQException
{
MessagePublishInfo bpb = (_messagePublishInfo != null ? _messagePublishInfo.get() : null);
if (bpb == null)
{
- MessageMetaData mmd = loadMessageMetaData(context, messageId);
+ MessageMetaData mmd = loadMessageMetaData(context);
bpb = mmd.getMessagePublishInfo();
}
@@ -168,12 +172,9 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
_redelivered = redelivered;
}
- public boolean isPersistent(StoreContext context, Long messageId) throws AMQException
+ public boolean isPersistent()
{
- //todo remove literal values to a constant file such as AMQConstants in common
- ContentHeaderBody chb = getContentHeaderBody(context, messageId);
- return chb.properties instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) chb.properties).getDeliveryMode() == 2;
+ return true;
}
/**
@@ -183,7 +184,7 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
* @param contentHeaderBody
* @throws AMQException
*/
- public void setPublishAndContentHeaderBody(StoreContext storeContext, Long messageId, MessagePublishInfo publishBody,
+ public void setPublishAndContentHeaderBody(StoreContext storeContext, MessagePublishInfo publishBody,
ContentHeaderBody contentHeaderBody)
throws AMQException
{
@@ -199,24 +200,15 @@ public class WeakReferenceMessageHandle implements AMQMessageHandle
MessageMetaData mmd = new MessageMetaData(publishBody, contentHeaderBody, _contentBodies.size(), arrivalTime);
- _messageStore.storeMessageMetaData(storeContext, messageId, mmd);
+ _messageStore.storeMessageMetaData(storeContext, _messageId, mmd);
- populateFromMessageMetaData(mmd);
- }
- public void removeMessage(StoreContext storeContext, Long messageId) throws AMQException
- {
- _messageStore.removeMessage(storeContext, messageId);
- }
-
- public void enqueue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException
- {
- _messageStore.enqueueMessage(storeContext, queue.getName(), messageId);
+ populateFromMessageMetaData(mmd);
}
- public void dequeue(StoreContext storeContext, Long messageId, AMQQueue queue) throws AMQException
+ public void removeMessage(StoreContext storeContext) throws AMQException
{
- _messageStore.dequeueMessage(storeContext, queue.getName(), messageId);
+ _messageStore.removeMessage(storeContext, _messageId);
}
public long getArrivalTime()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/WeightedSubscriptionManager.java b/java/broker/src/main/java/org/apache/qpid/server/queue/WeightedSubscriptionManager.java
deleted file mode 100644
index 6c71571807..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/WeightedSubscriptionManager.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-public interface WeightedSubscriptionManager extends SubscriptionManager
-{
- public int getWeight();
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 455983c6d8..63171d583a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -24,9 +24,17 @@ import org.apache.commons.configuration.Configuration;
import org.apache.log4j.Logger;
import org.apache.qpid.server.configuration.Configurator;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.server.management.ManagedObjectRegistry;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
+import org.apache.qpid.server.security.access.ACLPlugin;
+import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.mina.common.IoAcceptor;
import java.util.HashMap;
import java.util.Map;
+import java.net.InetSocketAddress;
/**
* An abstract application registry that provides access to configuration information and handles the
@@ -36,7 +44,7 @@ import java.util.Map;
*/
public abstract class ApplicationRegistry implements IApplicationRegistry
{
- private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
+ protected static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
private static Map<Integer, IApplicationRegistry> _instanceMap = new HashMap<Integer, IApplicationRegistry>();
@@ -48,6 +56,20 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public static final String DEFAULT_APPLICATION_REGISTRY = "org.apache.qpid.server.util.NullApplicationRegistry";
public static String _APPLICATION_REGISTRY = DEFAULT_APPLICATION_REGISTRY;
+ protected final Map<InetSocketAddress, IoAcceptor> _acceptors = new HashMap<InetSocketAddress, IoAcceptor>();
+
+ protected ManagedObjectRegistry _managedObjectRegistry;
+
+ protected AuthenticationManager _authenticationManager;
+
+ protected VirtualHostRegistry _virtualHostRegistry;
+
+ protected ACLPlugin _accessManager;
+
+ protected PrincipalDatabaseManager _databaseManager;
+
+ protected PluginManager _pluginManager;
+
static
{
Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownService()));
@@ -57,7 +79,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
public void run()
{
- _logger.info("Shutting down application registries...");
removeAll();
}
}
@@ -90,16 +111,29 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
+ /**
+ * Method to cleanly shutdown specified registry running in this JVM
+ *
+ * @param instanceID the instance to shutdown
+ */
+
public static void remove(int instanceID)
{
try
{
- _instanceMap.get(instanceID).close();
+ IApplicationRegistry instance = _instanceMap.get(instanceID);
+ if (instance != null)
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Shuting down ApplicationRegistry(" + instanceID + "):" + instance);
+ }
+ instance.close();
+ }
}
catch (Exception e)
{
- _logger.error("Error shutting down message store: " + e, e);
-
+ _logger.error("Error shutting down Application Registry(" + instanceID + "): " + e, e);
}
finally
{
@@ -107,6 +141,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
+ /** Method to cleanly shutdown all registries currently running in this JVM */
public static void removeAll()
{
Object[] keys = _instanceMap.keySet().toArray();
@@ -158,15 +193,36 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public void close() throws Exception
{
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Shutting down ApplicationRegistry:"+this);
+ }
+
+ //Stop incomming connections
+ unbind();
+
+ //Shutdown virtualhosts
for (VirtualHost virtualHost : getVirtualHostRegistry().getVirtualHosts())
{
virtualHost.close();
}
// close the rmi registry(if any) started for management
- if (getInstance().getManagedObjectRegistry() != null)
+ if (getManagedObjectRegistry() != null)
+ {
+ getManagedObjectRegistry().close();
+ }
+ }
+
+ private void unbind()
+ {
+ synchronized (_acceptors)
{
- getInstance().getManagedObjectRegistry().close();
+ for (InetSocketAddress bindAddress : _acceptors.keySet())
+ {
+ IoAcceptor acceptor = _acceptors.get(bindAddress);
+ acceptor.unbind(bindAddress);
+ }
}
}
@@ -175,6 +231,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _configuration;
}
+ public void addAcceptor(InetSocketAddress bindAddress, IoAcceptor acceptor)
+ {
+ synchronized (_acceptors)
+ {
+ _acceptors.put(bindAddress, acceptor);
+ }
+ }
+
public <T> T getConfiguredObject(Class<T> instanceType)
{
T instance = (T) _configuredObjects.get(instanceType);
@@ -195,9 +259,39 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return instance;
}
-
public static void setDefaultApplicationRegistry(String clazz)
{
_APPLICATION_REGISTRY = clazz;
}
+
+ public VirtualHostRegistry getVirtualHostRegistry()
+ {
+ return _virtualHostRegistry;
+ }
+
+ public ACLPlugin getAccessManager()
+ {
+ return _accessManager;
+ }
+
+ public ManagedObjectRegistry getManagedObjectRegistry()
+ {
+ return _managedObjectRegistry;
+ }
+
+ public PrincipalDatabaseManager getDatabaseManager()
+ {
+ return _databaseManager;
+ }
+
+ public AuthenticationManager getAuthenticationManager()
+ {
+ return _authenticationManager;
+ }
+
+ public PluginManager getPluginManager()
+ {
+ return _pluginManager;
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index 748e33ba7a..baab56a4a4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -48,23 +48,6 @@ import org.apache.qpid.AMQException;
public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
- private ManagedObjectRegistry _managedObjectRegistry;
-
- private AuthenticationManager _authenticationManager;
-
- private ACLPlugin _accessManager;
-
- private PrincipalDatabaseManager _databaseManager;
-
- private VirtualHostRegistry _virtualHostRegistry;
-
- private PluginManager _pluginManager;
-
-
- public ConfigurationFileApplicationRegistry(Configuration configuration)
- {
- super(configuration);
- }
public ConfigurationFileApplicationRegistry(File configurationURL) throws ConfigurationException
{
@@ -81,7 +64,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
}
- public static final Configuration config(File url) throws ConfigurationException
+ private static final Configuration config(File url) throws ConfigurationException
{
// We have to override the interpolate methods so that
// interpolation takes place accross the entirety of the
@@ -150,39 +133,9 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
}
-
- public VirtualHostRegistry getVirtualHostRegistry()
- {
- return _virtualHostRegistry;
- }
-
- public ACLPlugin getAccessManager()
- {
- return _accessManager;
- }
-
- public ManagedObjectRegistry getManagedObjectRegistry()
- {
- return _managedObjectRegistry;
- }
-
- public PrincipalDatabaseManager getDatabaseManager()
- {
- return _databaseManager;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
public Collection<String> getVirtualHostNames()
{
return getConfiguration().getList("virtualhosts.virtualhost.name");
}
- public PluginManager getPluginManager()
- {
- return _pluginManager;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
index ca10fbdba2..597ef042f9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.registry;
import java.util.Collection;
+import java.net.InetSocketAddress;
import org.apache.commons.configuration.Configuration;
import org.apache.qpid.server.management.ManagedObjectRegistry;
@@ -29,6 +30,7 @@ import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.mina.common.IoAcceptor;
public interface IApplicationRegistry
{
@@ -39,6 +41,10 @@ public interface IApplicationRegistry
*/
void initialise() throws Exception;
+ /**
+ * Shutdown this Registry
+ * @throws Exception - //fixme needs to be made more specific
+ */
void close() throws Exception;
/**
@@ -71,5 +77,12 @@ public interface IApplicationRegistry
ACLPlugin getAccessManager();
PluginManager getPluginManager();
-
+
+ /**
+ * Register any acceptors for this registry
+ * @param bindAddress The address that the acceptor has been bound with
+ * @param acceptor The acceptor in use
+ */
+ void addAcceptor(InetSocketAddress bindAddress, IoAcceptor acceptor);
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java
index 89cead69b3..86f155d862 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessResult.java
@@ -27,23 +27,23 @@ public class AccessResult
GRANTED, REFUSED
}
- StringBuilder _authorizer;
- AccessStatus _status;
+ private String _authorizer;
+ private AccessStatus _status;
public AccessResult(ACLPlugin authorizer, AccessStatus status)
{
_status = status;
- _authorizer = new StringBuilder(authorizer.getPluginName());
+ _authorizer = authorizer.getPluginName();
}
public void setAuthorizer(ACLPlugin authorizer)
{
- _authorizer.append(authorizer.getPluginName());
+ _authorizer += authorizer.getPluginName();
}
public String getAuthorizer()
{
- return _authorizer.toString();
+ return _authorizer;
}
public void setStatus(AccessStatus status)
@@ -58,8 +58,7 @@ public class AccessResult
public void addAuthorizer(ACLPlugin accessManager)
{
- _authorizer.insert(0, "->");
- _authorizer.insert(0, accessManager.getPluginName());
+ _authorizer = accessManager.getPluginName() + "->" + _authorizer;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java
index 126ff22d69..9b784069dd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/AllowAll.java
@@ -28,13 +28,9 @@ import org.apache.qpid.server.security.access.AccessResult;
import org.apache.qpid.server.security.access.Accessable;
import org.apache.qpid.server.security.access.Permission;
import org.apache.commons.configuration.Configuration;
-import org.apache.log4j.Logger;
public class AllowAll implements ACLPlugin
{
-
- private static final Logger _logger = ACLManager.getLogger();
-
public AccessResult authorise(AMQProtocolSession session, Permission permission, AMQMethodBody body, Object... parameters)
{
if (ACLManager.getLogger().isDebugEnabled())
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
index 0e3aea4de0..3f846b9dd0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.security.auth;
+import javax.security.sasl.SaslException;
+
public class AuthenticationResult
{
public enum AuthenticationStatus
@@ -29,15 +31,33 @@ public class AuthenticationResult
public AuthenticationStatus status;
public byte[] challenge;
+
+ private Exception cause;
+
+ public AuthenticationResult(AuthenticationStatus status)
+ {
+ this(null, status, null);
+ }
public AuthenticationResult(byte[] challenge, AuthenticationStatus status)
{
+ this(challenge, status, null);
+ }
+
+ public AuthenticationResult(AuthenticationStatus error, Exception cause)
+ {
+ this(null, error, cause);
+ }
+
+ public AuthenticationResult(byte[] challenge, AuthenticationStatus status, Exception cause)
+ {
this.status = status;
this.challenge = challenge;
+ this.cause = cause;
}
- public AuthenticationResult(AuthenticationStatus status)
+ public Exception getCause()
{
- this.status = status;
+ return cause;
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index f589140e8e..e5bf3edfca 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -230,12 +230,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
catch (SaslException e)
{
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
}
}
-
- public AuthenticationResult isAuthorize(VirtualHost vhost, String username)
- {
- return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
index 7842f376fb..9f56b8521a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
@@ -68,12 +68,15 @@ public class AmqPlainSaslServer implements SaslServer
PasswordCallback passwordCb = new PasswordCallback("prompt", false);
// TODO: should not get pwd as a String but as a char array...
String pwd = (String) ft.getString("PASSWORD");
- passwordCb.setPassword(pwd.toCharArray());
AuthorizeCallback authzCb = new AuthorizeCallback(username, username);
Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb};
_cbh.handle(callbacks);
- _complete = true;
- if (authzCb.isAuthorized())
+ String storedPwd = new String(passwordCb.getPassword());
+ if (storedPwd.equals(pwd))
+ {
+ _complete = true;
+ }
+ if (authzCb.isAuthorized() && _complete)
{
_authorizationId = authzCb.getAuthenticationID();
return null;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
index 36aeb77fe1..45fb9a4e42 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServer.java
@@ -72,17 +72,19 @@ public class PlainSaslServer implements SaslServer
// we do not care about the prompt but it throws if null
NameCallback nameCb = new NameCallback("prompt", authzid);
- // we do not care about the prompt but it throws if null
PasswordCallback passwordCb = new PasswordCallback("prompt", false);
// TODO: should not get pwd as a String but as a char array...
int passwordLen = response.length - authcidNullPosition - 1;
String pwd = new String(response, authcidNullPosition + 1, passwordLen, "utf8");
- passwordCb.setPassword(pwd.toCharArray());
AuthorizeCallback authzCb = new AuthorizeCallback(authzid, authzid);
Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb};
_cbh.handle(callbacks);
- _complete = true;
- if (authzCb.isAuthorized())
+ String storedPwd = new String(passwordCb.getPassword());
+ if (storedPwd.equals(pwd))
+ {
+ _complete = true;
+ }
+ if (authzCb.isAuthorized() && _complete)
{
_authorizationId = authzCb.getAuthenticationID();
return null;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
index bd980c696c..743a736884 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.store;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.MessageMetaData;
import org.apache.qpid.server.queue.QueueRegistry;
@@ -351,7 +352,8 @@ public class DerbyMessageStore implements MessageStore
String queueName = rs.getString(1);
String owner = rs.getString(2);
AMQShortString queueNameShortString = new AMQShortString(queueName);
- AMQQueue q = new AMQQueue(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost);
+ AMQQueue q = AMQQueueFactory.createAMQQueueImpl(queueNameShortString, true, owner == null ? null : new AMQShortString(owner), false, _virtualHost,
+ null);
_virtualHost.getQueueRegistry().registerQueue(q);
queueMap.put(queueNameShortString,q);
@@ -450,7 +452,8 @@ public class DerbyMessageStore implements MessageStore
argumentsFT = new FieldTable(buf,arguments.length());
}
- queue.bind(bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT, exchange);
+ queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT);
+
}
}
}
@@ -727,6 +730,11 @@ public class DerbyMessageStore implements MessageStore
public void createQueue(AMQQueue queue) throws AMQException
{
+ createQueue(queue, null);
+ }
+
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
+ {
_logger.debug("public void createQueue(AMQQueue queue = " + queue + "): called");
if (_state != State.RECOVERING)
@@ -762,9 +770,9 @@ public class DerbyMessageStore implements MessageStore
return connection;
}
- public void removeQueue(AMQShortString name) throws AMQException
+ public void removeQueue(final AMQQueue queue) throws AMQException
{
-
+ AMQShortString name = queue.getName();
_logger.debug("public void removeQueue(AMQShortString name = " + name + "): called");
Connection conn = null;
@@ -808,8 +816,9 @@ public class DerbyMessageStore implements MessageStore
}
- public void enqueueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
+ AMQShortString name = queue.getName();
boolean localTx = getOrCreateTransaction(context);
Connection conn = getConnection(context);
@@ -848,8 +857,9 @@ public class DerbyMessageStore implements MessageStore
}
- public void dequeueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
+ AMQShortString name = queue.getName();
boolean localTx = getOrCreateTransaction(context);
Connection conn = getConnection(context);
@@ -1276,6 +1286,11 @@ public class DerbyMessageStore implements MessageStore
}
+ public boolean isPersistent()
+ {
+ return true;
+ }
+
private void checkNotClosed() throws MessageStoreClosedException
{
if (_closed.get())
@@ -1300,7 +1315,8 @@ public class DerbyMessageStore implements MessageStore
public void process() throws AMQException
{
- _queue.process(_context, _queue.createEntry(_message), false);
+ _queue.enqueue(_context, _message);
+
}
}
@@ -1349,7 +1365,8 @@ public class DerbyMessageStore implements MessageStore
AMQQueue queue = queues.get(queueName);
if (queue == null)
{
- queue = new AMQQueue(queueName, false, null, false, _virtualHost);
+ queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, null, false, _virtualHost, null);
+
_virtualHost.getQueueRegistry().registerQueue(queue);
queues.put(queueName, queue);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index 7a6e0b011f..587c85fc12 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -26,9 +26,9 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.server.queue.MessageMetaData;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MessageMetaData;
import org.apache.qpid.server.virtualhost.VirtualHost;
import java.util.ArrayList;
@@ -121,22 +121,28 @@ public class MemoryMessageStore implements MessageStore
}
+
public void createQueue(AMQQueue queue) throws AMQException
{
+ // Not requred to do anything
+ }
+
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
+ {
// Not required to do anything
}
- public void removeQueue(AMQShortString name) throws AMQException
+ public void removeQueue(final AMQQueue queue) throws AMQException
{
// Not required to do anything
}
- public void enqueueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
// Not required to do anything
}
- public void dequeueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
// Not required to do anything
}
@@ -213,7 +219,12 @@ public class MemoryMessageStore implements MessageStore
return bodyList.get(index);
}
- private void checkNotClosed() throws MessageStoreClosedException
+ public boolean isPersistent()
+ {
+ return false;
+ }
+
+ private void checkNotClosed() throws MessageStoreClosedException
{
if (_closed.get())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
index 2a83d9b649..f2910acb77 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -27,8 +27,8 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.MessageMetaData;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
/**
@@ -136,35 +136,42 @@ public interface MessageStore
void createQueue(AMQQueue queue) throws AMQException;
/**
- * Removes the specified queue from the persistent store.
+ * Makes the specified queue persistent.
*
- * @param name The queue to remove.
+ * @param queue The queue to store.
*
+ * @param arguments The additional arguments to the binding
* @throws AMQException If the operation fails for any reason.
*/
- void removeQueue(AMQShortString name) throws AMQException;
+ void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException;
+
+ /**
+ * Removes the specified queue from the persistent store.
+ *
+ * @param queue The queue to remove.
+ * @throws AMQException If the operation fails for any reason.
+ */
+ void removeQueue(final AMQQueue queue) throws AMQException;
/**
* Places a message onto a specified queue, in a given transactional context.
*
* @param context The transactional context for the operation.
- * @param name The name of the queue to place the message on.
+ * @param queue The queue to place the message on.
* @param messageId The message to enqueue.
- *
* @throws AMQException If the operation fails for any reason.
*/
- void enqueueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException;
+ void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException;
/**
* Extracts a message from a specified queue, in a given transactional context.
*
* @param context The transactional context for the operation.
- * @param name The name of the queue to take the message from.
+ * @param queue The queue to place the message on.
* @param messageId The message to dequeue.
- *
* @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
*/
- void dequeueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException;
+ void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException;
/**
* Begins a transactional context.
@@ -258,4 +265,12 @@ public interface MessageStore
* @throws AMQException If the operation fails for any reason, or if the specified message does not exist.
*/
ContentChunk getContentBodyChunk(StoreContext context, Long messageId, int index) throws AMQException;
+
+ /**
+ * Is this store capable of persisting the data
+ *
+ * @return true if this store is capable of persisting data
+ */
+ boolean isPersistent();
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java b/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
index 3ee49d58cf..fdb56a1a55 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/StoreContext.java
@@ -37,7 +37,7 @@ public class StoreContext
public StoreContext()
{
- _name = super.toString();
+ _name = "StoreContext";
}
public StoreContext(String name)
@@ -52,7 +52,10 @@ public class StoreContext
public void setPayload(Object payload)
{
- _logger.debug("public void setPayload(Object payload = " + payload + "): called");
+ if(_logger.isDebugEnabled())
+ {
+ _logger.debug("public void setPayload(Object payload = " + payload + "): called");
+ }
_payload = payload;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java
new file mode 100644
index 0000000000..fbc8b3af7d
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/ClientDeliveryMethod.java
@@ -0,0 +1,29 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.AMQException;
+
+public interface ClientDeliveryMethod
+{
+ void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) throws AMQException;
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java
new file mode 100644
index 0000000000..e2ed4104de
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/RecordDeliveryMethod.java
@@ -0,0 +1,28 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.queue.QueueEntry;
+
+public interface RecordDeliveryMethod
+{
+ void recordMessageDelivery(final Subscription sub, final QueueEntry entry, final long deliveryTag);
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
index 96ce6743ec..408defe453 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java
@@ -18,46 +18,77 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
-
-import java.util.Queue;
+package org.apache.qpid.server.subscription;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueEntry;
public interface Subscription
{
- void send(QueueEntry msg, AMQQueue queue) throws AMQException;
- boolean isSuspended();
- void queueDeleted(AMQQueue queue) throws AMQException;
+ public static enum State
+ {
+ ACTIVE,
+ SUSPENDED,
+ CLOSED
+ }
- boolean filtersMessages();
+ public static interface StateListener
+ {
+ public void stateChange(Subscription sub, State oldState, State newState);
+ }
- boolean hasInterest(QueueEntry msg);
+ AMQQueue getQueue();
- Queue<QueueEntry> getPreDeliveryQueue();
+ QueueEntry.SubscriptionAcquiredState getOwningState();
- Queue<QueueEntry> getResendQueue();
+ void setQueue(AMQQueue queue);
- Queue<QueueEntry> getNextQueue(Queue<QueueEntry> messages);
+ AMQChannel getChannel();
- void enqueueForPreDelivery(QueueEntry msg, boolean deliverFirst);
+ AMQShortString getConsumerTag();
- void close();
+ boolean isSuspended();
+
+ boolean hasInterest(QueueEntry msg);
+
+ boolean isAutoClose();
boolean isClosed();
boolean isBrowser();
+ void close();
+
+ boolean filtersMessages();
+
+ void send(QueueEntry msg) throws AMQException;
+
+ void queueDeleted(AMQQueue queue);
+
+
boolean wouldSuspend(QueueEntry msg);
- void addToResendQueue(QueueEntry msg);
+ void getSendLock();
+ void releaseSendLock();
+
+ void resend(final QueueEntry entry) throws AMQException;
+
+ void restoreCredit(final QueueEntry queueEntry);
+
+ void setStateListener(final StateListener listener);
+
+ QueueEntry getLastSeenEntry();
+
+ boolean setLastSeenEntry(QueueEntry expected, QueueEntry newValue);
+
+
+ boolean isActive();
- Object getSendLock();
- AMQChannel getChannel();
- void start();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
index 917f7c4e97..ce0362d73f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
@@ -18,12 +18,15 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.subscription;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.AMQChannel;
/**
* Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory
@@ -34,10 +37,23 @@ import org.apache.qpid.server.protocol.AMQProtocolSession;
*/
public interface SubscriptionFactory
{
- Subscription createSubscription(int channel, AMQProtocolSession protocolSession, AMQShortString consumerTag, boolean acks,
- FieldTable filters, boolean noLocal, AMQQueue queue) throws AMQException;
+ Subscription createSubscription(int channel,
+ AMQProtocolSession protocolSession,
+ AMQShortString consumerTag,
+ boolean acks,
+ FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager) throws AMQException;
- Subscription createSubscription(int channel, AMQProtocolSession protocolSession, AMQShortString consumerTag)
+ Subscription createSubscription(AMQChannel channel,
+ AMQProtocolSession protocolSession,
+ AMQShortString consumerTag,
+ boolean acks,
+ FieldTable filters,
+ boolean noLocal,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod clientMethod,
+ RecordDeliveryMethod recordMethod
+ )
throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
new file mode 100644
index 0000000000..5badbad642
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactory;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.common.AMQPFilterTypes;
+
+public class SubscriptionFactoryImpl implements SubscriptionFactory
+{
+
+ /* private SubscriptionFactoryImpl()
+ {
+
+ }*/
+
+ public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, boolean acks, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager) throws AMQException
+ {
+ AMQChannel channel = protocolSession.getChannel(channelId);
+ if (channel == null)
+ {
+ throw new AMQException(AMQConstant.NOT_FOUND, "channel :" + channelId + " not found in protocol session");
+ }
+ ClientDeliveryMethod clientMethod = channel.getClientDeliveryMethod();
+ RecordDeliveryMethod recordMethod = channel.getRecordDeliveryMethod();
+
+
+ return createSubscription(channel, protocolSession, consumerTag, acks, filters,
+ noLocal,
+ creditManager,
+ clientMethod,
+ recordMethod
+ );
+ }
+
+ public Subscription createSubscription(final AMQChannel channel,
+ final AMQProtocolSession protocolSession,
+ final AMQShortString consumerTag,
+ final boolean acks,
+ final FieldTable filters,
+ final boolean noLocal,
+ final FlowCreditManager creditManager,
+ final ClientDeliveryMethod clientMethod,
+ final RecordDeliveryMethod recordMethod
+ )
+ throws AMQException
+ {
+ boolean isBrowser;
+
+ if (filters != null)
+ {
+ Boolean isBrowserObj = (Boolean) filters.get(AMQPFilterTypes.NO_CONSUME.getValue());
+ isBrowser = (isBrowserObj != null) && isBrowserObj.booleanValue();
+ }
+ else
+ {
+ isBrowser = false;
+ }
+
+ if(isBrowser)
+ {
+ return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ }
+ else if(acks)
+ {
+ return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ }
+ else
+ {
+ return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ }
+ }
+
+
+ public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
new file mode 100644
index 0000000000..556b87590c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java
@@ -0,0 +1,605 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.subscription;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.common.ClientProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.filter.FilterManagerFactory;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.store.StoreContext;
+
+/**
+ * Encapsulation of a supscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag
+ * that was given out by the broker and the channel id. <p/>
+ */
+public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener
+{
+
+ private StateListener _stateListener = new StateListener()
+ {
+
+ public void stateChange(Subscription sub, State oldState, State newState)
+ {
+
+ }
+ };
+
+
+ private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE);
+ private final AtomicReference<QueueEntry> _queueContext = new AtomicReference<QueueEntry>(null);
+ private final ClientDeliveryMethod _deliveryMethod;
+ private final RecordDeliveryMethod _recordMethod;
+
+ private QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
+ private final Lock _stateChangeLock;
+
+ static final class BrowserSubscription extends SubscriptionImpl
+ {
+ public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ }
+
+
+ public boolean isBrowser()
+ {
+ return true;
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ * @param msg The message to send
+ * @throws AMQException
+ */
+ public void send(QueueEntry msg) throws AMQException
+ {
+ // We don't decrement the reference here as we don't want to consume the message
+ // but we do want to send it to the client.
+
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
+ sendToClient(msg, deliveryTag);
+ }
+
+ }
+ }
+
+ public static class NoAckSubscription extends SubscriptionImpl
+ {
+ public NoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ }
+
+
+ public boolean isBrowser()
+ {
+ return false;
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ * @param entry The message to send
+ * @throws AMQException
+ */
+ public void send(QueueEntry entry) throws AMQException
+ {
+
+ StoreContext storeContext = getChannel().getStoreContext();
+ try
+ { // if we do not need to wait for client acknowledgements
+ // we can decrement the reference count immediately.
+
+ // By doing this _before_ the send we ensure that it
+ // doesn't get sent if it can't be dequeued, preventing
+ // duplicate delivery on recovery.
+
+ // The send may of course still fail, in which case, as
+ // the message is unacked, it will be lost.
+ entry.dequeue(storeContext);
+
+
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
+
+ sendToClient(entry, deliveryTag);
+
+ }
+ entry.dispose(storeContext);
+ }
+ finally
+ {
+ //Only set delivered if it actually was writen successfully..
+ // using a try->finally would set it even if an error occured.
+ // Is this what we want?
+
+ entry.setDeliveredToSubscription();
+ }
+ }
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return false;
+ }
+
+ }
+
+ static final class AckSubscription extends SubscriptionImpl
+ {
+ public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ }
+
+ public boolean isBrowser()
+ {
+ return false;
+ }
+
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ * @param entry The message to send
+ * @throws AMQException
+ */
+ public void send(QueueEntry entry) throws AMQException
+ {
+
+ try
+ { // if we do not need to wait for client acknowledgements
+ // we can decrement the reference count immediately.
+
+ // By doing this _before_ the send we ensure that it
+ // doesn't get sent if it can't be dequeued, preventing
+ // duplicate delivery on recovery.
+
+ // The send may of course still fail, in which case, as
+ // the message is unacked, it will be lost.
+
+ synchronized (getChannel())
+ {
+ long deliveryTag = getChannel().getNextDeliveryTag();
+
+
+ recordMessageDelivery(entry, deliveryTag);
+ sendToClient(entry, deliveryTag);
+
+
+ }
+ }
+ finally
+ {
+ //Only set delivered if it actually was writen successfully..
+ // using a try->finally would set it even if an error occured.
+ // Is this what we want?
+
+ entry.setDeliveredToSubscription();
+ }
+ }
+
+
+ }
+
+
+ private static final Logger _logger = Logger.getLogger(SubscriptionImpl.class);
+
+ private final AMQChannel _channel;
+
+ private final AMQShortString _consumerTag;
+
+
+ private final boolean _noLocal;
+
+ private final FlowCreditManager _creditManager;
+
+ private FilterManager _filters;
+
+ private final Boolean _autoClose;
+
+
+ private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString();
+
+ private AMQQueue _queue;
+ private final AtomicBoolean _deleted = new AtomicBoolean(false);
+
+
+
+
+ public SubscriptionImpl(AMQChannel channel , AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable arguments,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod)
+ throws AMQException
+ {
+
+ _channel = channel;
+ _consumerTag = consumerTag;
+
+ _creditManager = creditManager;
+ creditManager.addStateListener(this);
+
+ _noLocal = noLocal;
+
+
+ _filters = FilterManagerFactory.createManager(arguments);
+
+ _deliveryMethod = deliveryMethod;
+ _recordMethod = recordMethod;
+
+
+ _stateChangeLock = new ReentrantLock();
+
+
+ if (arguments != null)
+ {
+ Object autoClose = arguments.get(AMQPFilterTypes.AUTO_CLOSE.getValue());
+ if (autoClose != null)
+ {
+ _autoClose = (Boolean) autoClose;
+ }
+ else
+ {
+ _autoClose = false;
+ }
+ }
+ else
+ {
+ _autoClose = false;
+ }
+
+
+ }
+
+
+
+ public synchronized void setQueue(AMQQueue queue)
+ {
+ if(getQueue() != null)
+ {
+ throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue());
+ }
+ _queue = queue;
+ }
+
+ public String toString()
+ {
+ String subscriber = "[channel=" + _channel +
+ ", consumerTag=" + _consumerTag +
+ ", session=" + getProtocolSession().getKey() ;
+
+ return subscriber + "]";
+ }
+
+ /**
+ * This method can be called by each of the publisher threads. As a result all changes to the channel object must be
+ * thread safe.
+ *
+ * @param msg The message to send
+ * @throws AMQException
+ */
+ abstract public void send(QueueEntry msg) throws AMQException;
+
+
+ public boolean isSuspended()
+ {
+ return !isActive() || _channel.isSuspended() || _deleted.get();
+ }
+
+ /**
+ * Callback indicating that a queue has been deleted.
+ *
+ * @param queue The queue to delete
+ */
+ public void queueDeleted(AMQQueue queue)
+ {
+ _deleted.set(true);
+// _channel.queueDeleted(queue);
+ }
+
+ public boolean filtersMessages()
+ {
+ return _filters != null || _noLocal;
+ }
+
+ public boolean hasInterest(QueueEntry entry)
+ {
+ //check that the message hasn't been rejected
+ if (entry.isRejectedBy(this))
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Subscription:" + debugIdentity() + " rejected message:" + entry.debugIdentity());
+ }
+// return false;
+ }
+
+
+
+ //todo - client id should be recoreded and this test removed but handled below
+ if (_noLocal)
+ {
+ final Object publisherId = entry.getMessage().getPublisherClientInstance();
+
+ // We don't want local messages so check to see if message is one we sent
+ Object localInstance;
+
+ if (publisherId != null && (getProtocolSession().getClientProperties() != null) &&
+ (localInstance = getProtocolSession().getClientProperties().getObject(CLIENT_PROPERTIES_INSTANCE)) != null)
+ {
+ if(publisherId.equals(localInstance))
+ {
+ return false;
+ }
+ }
+ else
+ {
+
+ localInstance = getProtocolSession().getClientIdentifier();
+ //todo - client id should be recoreded and this test removed but handled here
+
+
+ if (localInstance != null && localInstance.equals(entry.getMessage().getPublisherIdentifier()))
+ {
+ return false;
+ }
+ }
+
+
+ }
+
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("(" + debugIdentity() + ") checking filters for message (" + entry.debugIdentity());
+ }
+ return checkFilters(entry);
+
+ }
+
+ private String id = String.valueOf(System.identityHashCode(this));
+
+ private String debugIdentity()
+ {
+ return id;
+ }
+
+ private boolean checkFilters(QueueEntry msg)
+ {
+ return (_filters == null) || _filters.allAllow(msg.getMessage());
+ }
+
+ public boolean isAutoClose()
+ {
+ return _autoClose;
+ }
+
+ public FlowCreditManager getCreditManager()
+ {
+ return _creditManager;
+ }
+
+
+ public void close()
+ {
+ boolean closed = false;
+ State state = getState();
+
+ _stateChangeLock.lock();
+ try
+ {
+ while(!closed && state != State.CLOSED)
+ {
+ closed = _state.compareAndSet(state, State.CLOSED);
+ if(!closed)
+ {
+ state = getState();
+ }
+ else
+ {
+ _stateListener.stateChange(this,state, State.CLOSED);
+ }
+ }
+ _creditManager.removeListener(this);
+ }
+ finally
+ {
+ _stateChangeLock.unlock();
+ }
+
+
+ if (closed)
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Called close() on a closed subscription");
+ }
+
+ return;
+ }
+
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Closing subscription (" + debugIdentity() + "):" + this);
+ }
+ }
+
+ public boolean isClosed()
+ {
+ return getState() == State.CLOSED;
+ }
+
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return !_creditManager.useCreditForMessage(msg.getMessage());//_channel.wouldSuspend(msg.getMessage());
+ }
+
+ public void getSendLock()
+ {
+ _stateChangeLock.lock();
+ }
+
+ public void releaseSendLock()
+ {
+ _stateChangeLock.unlock();
+ }
+
+ public void resend(final QueueEntry entry) throws AMQException
+ {
+ _queue.resend(entry, this);
+ }
+
+ public AMQChannel getChannel()
+ {
+ return _channel;
+ }
+
+ public AMQShortString getConsumerTag()
+ {
+ return _consumerTag;
+ }
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _channel.getProtocolSession();
+ }
+
+ public AMQQueue getQueue()
+ {
+ return _queue;
+ }
+
+ public void restoreCredit(final QueueEntry queueEntry)
+ {
+ _creditManager.addCredit(1, queueEntry.getSize());
+ }
+
+
+ public void creditStateChanged(boolean hasCredit)
+ {
+
+ if(hasCredit)
+ {
+ if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE))
+ {
+ _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE);
+ }
+ else
+ {
+ // this is a hack to get round the issue of increasing bytes credit
+ _stateListener.stateChange(this, State.ACTIVE, State.ACTIVE);
+ }
+ }
+ else
+ {
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+ }
+ }
+
+ public State getState()
+ {
+ return _state.get();
+ }
+
+
+ public void setStateListener(final StateListener listener)
+ {
+ _stateListener = listener;
+ }
+
+
+ public QueueEntry getLastSeenEntry()
+ {
+ return _queueContext.get();
+ }
+
+ public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newvalue)
+ {
+ return _queueContext.compareAndSet(expected,newvalue);
+ }
+
+
+ protected void sendToClient(final QueueEntry entry, final long deliveryTag)
+ throws AMQException
+ {
+ _deliveryMethod.deliverToClient(this,entry,deliveryTag);
+ }
+
+
+ protected void recordMessageDelivery(final QueueEntry entry, final long deliveryTag)
+ {
+ _recordMethod.recordMessageDelivery(this,entry,deliveryTag);
+ }
+
+
+ public boolean isActive()
+ {
+ return getState() == State.ACTIVE;
+ }
+
+ public QueueEntry.SubscriptionAcquiredState getOwningState()
+ {
+ return _owningState;
+ }
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
new file mode 100644
index 0000000000..3fbb6bfa4a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
@@ -0,0 +1,247 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.subscription;
+
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.subscription.Subscription;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.nio.ByteBuffer;
+
+public class SubscriptionList
+{
+
+ private final SubscriptionNode _head = new SubscriptionNode();
+
+ private AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
+ private final AMQQueue _queue;
+ private AtomicInteger _size = new AtomicInteger();
+
+
+ public final class SubscriptionNode
+ {
+ private final AtomicBoolean _deleted = new AtomicBoolean();
+ private final AtomicReference<SubscriptionNode> _next = new AtomicReference<SubscriptionNode>();
+ private final Subscription _sub;
+
+
+ public SubscriptionNode()
+ {
+
+ _sub = null;
+ _deleted.set(true);
+ }
+
+ public SubscriptionNode(final Subscription sub)
+ {
+ _sub = sub;
+ }
+
+
+ public SubscriptionNode getNext()
+ {
+
+ SubscriptionNode next = nextNode();
+ while(next != null && next.isDeleted())
+ {
+
+ final SubscriptionNode newNext = next.nextNode();
+ if(newNext != null)
+ {
+ _next.compareAndSet(next, newNext);
+ next = nextNode();
+ }
+ else
+ {
+ next = null;
+ }
+
+ }
+ return next;
+ }
+
+ private SubscriptionNode nextNode()
+ {
+ return _next.get();
+ }
+
+ public boolean isDeleted()
+ {
+ return _deleted.get();
+ }
+
+
+ public boolean delete()
+ {
+ if(_deleted.compareAndSet(false,true))
+ {
+ _size.decrementAndGet();
+ advanceHead();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ public Subscription getSubscription()
+ {
+ return _sub;
+ }
+ }
+
+
+ public SubscriptionList(AMQQueue queue)
+ {
+ _queue = queue;
+ }
+
+ private void advanceHead()
+ {
+ SubscriptionNode head = _head.nextNode();
+ while(head._next.get() != null && head.isDeleted())
+ {
+
+ final SubscriptionNode newhead = head.nextNode();
+ if(newhead != null)
+ {
+ _head._next.compareAndSet(head, newhead);
+ }
+ head = _head.nextNode();
+ }
+ }
+
+
+ public SubscriptionNode add(Subscription sub)
+ {
+ SubscriptionNode node = new SubscriptionNode(sub);
+ for (;;)
+ {
+ SubscriptionNode tail = _tail.get();
+ SubscriptionNode next = tail.nextNode();
+ if (tail == _tail.get())
+ {
+ if (next == null)
+ {
+ if (tail._next.compareAndSet(null, node))
+ {
+ _tail.compareAndSet(tail, node);
+ _size.incrementAndGet();
+ return node;
+ }
+ }
+ else
+ {
+ _tail.compareAndSet(tail, next);
+ }
+ }
+ }
+
+ }
+
+ public boolean remove(Subscription sub)
+ {
+ SubscriptionNode node = _head.getNext();
+ while(node != null)
+ {
+ if(sub.equals(node._sub) && node.delete())
+ {
+ return true;
+ }
+ node = node.getNext();
+ }
+ return false;
+ }
+
+
+ public class SubscriptionNodeIterator
+ {
+
+ private SubscriptionNode _lastNode;
+
+ SubscriptionNodeIterator(SubscriptionNode startNode)
+ {
+ _lastNode = startNode;
+ }
+
+
+ public boolean atTail()
+ {
+ return _lastNode.nextNode() == null;
+ }
+
+ public SubscriptionNode getNode()
+ {
+
+ return _lastNode;
+
+ }
+
+ public boolean advance()
+ {
+
+ if(!atTail())
+ {
+ SubscriptionNode nextNode = _lastNode.nextNode();
+ while(nextNode.isDeleted() && nextNode.nextNode() != null)
+ {
+ nextNode = nextNode.nextNode();
+ }
+ _lastNode = nextNode;
+ return true;
+
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+
+ public SubscriptionNodeIterator iterator()
+ {
+ return new SubscriptionNodeIterator(_head);
+ }
+
+
+ public SubscriptionNode getHead()
+ {
+ return _head;
+ }
+
+ public int size()
+ {
+ return _size.get();
+ }
+
+
+
+}
+
+
+
diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java
index 23aaf56876..b67bb98e28 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ConnectorConfiguration.java
@@ -97,6 +97,10 @@ public class ConnectorConfiguration
defaultValue = "false")
public boolean _multiThreadNIO;
+ @Configured(path = "advanced.useWriteBiasedPool",
+ defaultValue = "false")
+ public boolean useBiasedWrites;
+
public IoAcceptor createAcceptor()
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java b/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java
deleted file mode 100644
index 988f589339..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.txn;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.NoConsumersException;
-import org.apache.qpid.server.store.StoreContext;
-
-import java.util.List;
-
-/**
- * @author Apache Software Foundation
- */
-public class CleanupMessageOperation implements TxnOp
-{
- private static final Logger _log = Logger.getLogger(CleanupMessageOperation.class);
-
- private final AMQMessage _msg;
-
- private final List<RequiredDeliveryException> _returns;
-
- public CleanupMessageOperation(AMQMessage msg, List<RequiredDeliveryException> returns)
- {
- _msg = msg;
- _returns = returns;
- }
-
- public void prepare(StoreContext context) throws AMQException
- { }
-
- public void undoPrepare()
- {
- // don't need to do anything here, if the store's txn failed
- // when processing prepare then the message was not stored
- // or enqueued on any queues and can be discarded
- }
-
- public void commit(StoreContext context)
- {
- // No-op can't be done here has this is before the message has been attempted to be delivered.
- /*try
- {
- _msg.checkDeliveredToConsumer();
- }
- catch (NoConsumersException e)
- {
- _returns.add(e);
- }*/
- }
-
- public void rollback(StoreContext context)
- {
- // NO OP
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
index 2307b94566..3c71282c57 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
@@ -24,18 +24,16 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.ack.TxAck;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.NoConsumersException;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreContext;
-import java.util.LinkedList;
import java.util.List;
+import java.util.ArrayList;
/** A transactional context that only supports local transactions. */
public class LocalTransactionalContext implements TransactionalContext
@@ -44,7 +42,7 @@ public class LocalTransactionalContext implements TransactionalContext
private final TxnBuffer _txnBuffer = new TxnBuffer();
- private final List<DeliveryDetails> _postCommitDeliveryList = new LinkedList<DeliveryDetails>();
+ private final List<DeliveryAction> _postCommitDeliveryList = new ArrayList<DeliveryAction>();
/**
* We keep hold of the ack operation so that we can consolidate acks, i.e. multiple acks within a txn are
@@ -52,81 +50,120 @@ public class LocalTransactionalContext implements TransactionalContext
*/
private TxAck _ackOp;
- private List<RequiredDeliveryException> _returnMessages;
-
- private final MessageStore _messageStore;
-
- private final StoreContext _storeContext;
-
private boolean _inTran = false;
/** Are there messages to deliver. NOT Has the message been delivered */
private boolean _messageDelivered = false;
+ private final AMQChannel _channel;
+
- private static class DeliveryDetails
+ private abstract class DeliveryAction
{
- public QueueEntry entry;
- private boolean deliverFirst;
+ abstract public void process() throws AMQException;
+
+ }
+
+ private class RequeueAction extends DeliveryAction
+ {
+ public QueueEntry entry;
- public DeliveryDetails(QueueEntry entry, boolean deliverFirst)
+ public RequeueAction(QueueEntry entry)
{
this.entry = entry;
- this.deliverFirst = deliverFirst;
+ }
+
+ public void process() throws AMQException
+ {
+ entry.requeue(getStoreContext());
}
}
- public LocalTransactionalContext(MessageStore messageStore, StoreContext storeContext,
- List<RequiredDeliveryException> returnMessages)
+ private class PublishAction extends DeliveryAction
{
- _messageStore = messageStore;
- _storeContext = storeContext;
- _returnMessages = returnMessages;
- // _txnBuffer.enlist(new StoreMessageOperation(messageStore));
+ private final AMQQueue _queue;
+ private final AMQMessage _message;
+
+ public PublishAction(final AMQQueue queue, final AMQMessage message)
+ {
+ _queue = queue;
+ _message = message;
+ }
+
+ public void process() throws AMQException
+ {
+
+ _message.incrementReference();
+ try
+ {
+ QueueEntry entry = _queue.enqueue(getStoreContext(),_message);
+
+ if(entry.immediateAndNotDelivered())
+ {
+ getReturnMessages().add(new NoConsumersException(_message));
+ }
+ }
+ finally
+ {
+ _message.decrementReference(getStoreContext());
+ }
+ }
+ }
+
+ public LocalTransactionalContext(final AMQChannel channel)
+ {
+ _channel = channel;
}
public StoreContext getStoreContext()
{
- return _storeContext;
+ return _channel.getStoreContext();
}
+ public List<RequiredDeliveryException> getReturnMessages()
+ {
+ return _channel.getReturnMessages();
+ }
+
+ public MessageStore getMessageStore()
+ {
+ return _channel.getMessageStore();
+ }
+
+
public void rollback() throws AMQException
{
- _txnBuffer.rollback(_storeContext);
+ _txnBuffer.rollback(getStoreContext());
// Hack to deal with uncommitted non-transactional writes
- if (_messageStore.inTran(_storeContext))
+ if (getMessageStore().inTran(getStoreContext()))
{
- _messageStore.abortTran(_storeContext);
+ getMessageStore().abortTran(getStoreContext());
_inTran = false;
}
_postCommitDeliveryList.clear();
}
- public void deliver(QueueEntry entry, boolean deliverFirst) throws AMQException
+ public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException
{
// A publication will result in the enlisting of several
// TxnOps. The first is an op that will store the message.
// Following that (and ordering is important), an op will
// be added for every queue onto which the message is
- // enqueued. Finally a cleanup op will be added to decrement
- // the reference associated with the routing.
- // message.incrementReference();
- _postCommitDeliveryList.add(new DeliveryDetails(entry, deliverFirst));
+ // enqueued.
+ _postCommitDeliveryList.add(new PublishAction(queue, message));
_messageDelivered = true;
- _txnBuffer.enlist(new CleanupMessageOperation(entry.getMessage(), _returnMessages));
- /*_txnBuffer.enlist(new DeliverMessageOperation(message, queue));
- if (_log.isDebugEnabled())
- {
- _log.debug("Incrementing ref count on message and enlisting cleanup operation - id " +
- message.getMessageId());
- }
- message.incrementReference();
+
+ }
+
+ public void requeue(QueueEntry entry) throws AMQException
+ {
+ _postCommitDeliveryList.add(new RequeueAction(entry));
_messageDelivered = true;
- */
}
+
private void checkAck(long deliveryTag, UnacknowledgedMessageMap unacknowledgedMessageMap) throws AMQException
{
if (!unacknowledgedMessageMap.contains(deliveryTag))
@@ -147,10 +184,8 @@ public class LocalTransactionalContext implements TransactionalContext
// as new acks come in. If this is the first ack in the txn
// we will need to create and enlist the op.
if (_ackOp == null)
- {
-
+ {
_ackOp = new TxAck(unacknowledgedMessageMap);
-
_txnBuffer.enlist(_ackOp);
}
// update the op to include this ack request
@@ -189,7 +224,7 @@ public class LocalTransactionalContext implements TransactionalContext
_log.debug("Starting transaction on message store: " + this);
}
- _messageStore.beginTran(_storeContext);
+ getMessageStore().beginTran(getStoreContext());
_inTran = true;
}
}
@@ -212,22 +247,22 @@ public class LocalTransactionalContext implements TransactionalContext
if (_messageDelivered && _inTran)
{
- _txnBuffer.enlist(new StoreMessageOperation(_messageStore));
+ _txnBuffer.enlist(new StoreMessageOperation(getMessageStore()));
}
// fixme fail commit here ... QPID-440
try
{
- _txnBuffer.commit(_storeContext);
+ _txnBuffer.commit(getStoreContext());
}
finally
{
_messageDelivered = false;
- _inTran = _messageStore.inTran(_storeContext);
+ _inTran = getMessageStore().inTran(getStoreContext());
}
try
{
- postCommitDelivery(_returnMessages);
+ postCommitDelivery();
}
catch (AMQException e)
{
@@ -236,7 +271,7 @@ public class LocalTransactionalContext implements TransactionalContext
}
}
- private void postCommitDelivery(List<RequiredDeliveryException> returnMessages) throws AMQException
+ private void postCommitDelivery() throws AMQException
{
if (_log.isDebugEnabled())
{
@@ -245,18 +280,9 @@ public class LocalTransactionalContext implements TransactionalContext
try
{
- for (DeliveryDetails dd : _postCommitDeliveryList)
+ for (DeliveryAction dd : _postCommitDeliveryList)
{
- dd.entry.process(_storeContext, dd.deliverFirst);
-
- try
- {
- dd.entry.checkDeliveredToConsumer();
- }
- catch (NoConsumersException nce)
- {
- returnMessages.add(nce);
- }
+ dd.process();
}
}
finally
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java b/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java
index cac3489f4c..28af36e3db 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/NonTransactionalContext.java
@@ -22,19 +22,14 @@ package org.apache.qpid.server.txn;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.ack.UnacknowledgedMessage;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.NoConsumersException;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoreContext;
@@ -49,6 +44,8 @@ public class NonTransactionalContext implements TransactionalContext
/** Where to put undeliverable messages */
private final List<RequiredDeliveryException> _returnMessages;
+
+
private final MessageStore _messageStore;
private final StoreContext _storeContext;
@@ -57,12 +54,6 @@ public class NonTransactionalContext implements TransactionalContext
private boolean _inTran;
public NonTransactionalContext(MessageStore messageStore, StoreContext storeContext, AMQChannel channel,
- List<RequiredDeliveryException> returnMessages, Set<Long> browsedAcks)
- {
- this(messageStore,storeContext,channel,returnMessages);
- }
-
- public NonTransactionalContext(MessageStore messageStore, StoreContext storeContext, AMQChannel channel,
List<RequiredDeliveryException> returnMessages)
{
_channel = channel;
@@ -97,19 +88,22 @@ public class NonTransactionalContext implements TransactionalContext
// Does not apply to this context
}
- public void deliver(QueueEntry entry, boolean deliverFirst) throws AMQException
+ public void deliver(final AMQQueue queue, AMQMessage message) throws AMQException
{
- try
+ QueueEntry entry = queue.enqueue(_storeContext, message);
+
+ //following check implements the functionality
+ //required by the 'immediate' flag:
+ if(entry.immediateAndNotDelivered())
{
- entry.process(_storeContext, deliverFirst);
- //following check implements the functionality
- //required by the 'immediate' flag:
- entry.checkDeliveredToConsumer();
- }
- catch (NoConsumersException e)
- {
- _returnMessages.add(e);
+ _returnMessages.add(new NoConsumersException(entry.getMessage()));
}
+
+ }
+
+ public void requeue(QueueEntry entry) throws AMQException
+ {
+ entry.requeue(_storeContext);
}
public void acknowledgeMessage(final long deliveryTag, long lastDeliveryTag,
@@ -118,7 +112,7 @@ public class NonTransactionalContext implements TransactionalContext
{
final boolean debug = _log.isDebugEnabled();
-
+ ;
if (multiple)
{
if (deliveryTag == 0)
@@ -130,7 +124,7 @@ public class NonTransactionalContext implements TransactionalContext
unacknowledgedMessageMap.size());
unacknowledgedMessageMap.visit(new UnacknowledgedMessageMap.Visitor()
{
- public boolean callback(UnacknowledgedMessage message) throws AMQException
+ public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException
{
if (debug)
{
@@ -159,28 +153,13 @@ public class NonTransactionalContext implements TransactionalContext
throw new AMQException("Multiple ack on delivery tag " + deliveryTag + " not known for channel");
}
- LinkedList<UnacknowledgedMessage> acked = new LinkedList<UnacknowledgedMessage>();
- unacknowledgedMessageMap.drainTo(acked, deliveryTag);
- for (UnacknowledgedMessage msg : acked)
- {
- if (debug)
- {
- _log.debug("Discarding message: " + msg.getMessage().getMessageId());
- }
- if(msg.getMessage().isPersistent())
- {
- beginTranIfNecessary();
- }
-
- //Message has been ack so discard it. This will dequeue and decrement the reference.
- msg.discard(_storeContext);
- }
+ unacknowledgedMessageMap.drainTo(deliveryTag, _storeContext);
}
}
else
{
- UnacknowledgedMessage msg;
- msg = unacknowledgedMessageMap.remove(deliveryTag);
+ QueueEntry msg;
+ msg = unacknowledgedMessageMap.get(deliveryTag);
if (msg == null)
{
@@ -202,19 +181,20 @@ public class NonTransactionalContext implements TransactionalContext
//Message has been ack so discard it. This will dequeue and decrement the reference.
msg.discard(_storeContext);
+ unacknowledgedMessageMap.remove(deliveryTag);
+
+
if (debug)
{
_log.debug("Received non-multiple ack for messaging with delivery tag " + deliveryTag + " msg id " +
msg.getMessage().getMessageId());
}
}
-
if(_inTran)
{
_messageStore.commitTran(_storeContext);
_inTran = false;
}
-
}
public void messageFullyReceived(boolean persistent) throws AMQException
@@ -228,6 +208,6 @@ public class NonTransactionalContext implements TransactionalContext
public void messageProcessed(AMQProtocolSession protocolSession) throws AMQException
{
- _channel.processReturns(protocolSession);
+ _channel.processReturns();
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java b/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java
index 6016ecc1a5..647ba66fb4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/TransactionalContext.java
@@ -25,6 +25,7 @@ import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.StoreContext;
/**
@@ -106,18 +107,26 @@ public interface TransactionalContext
void rollback() throws AMQException;
/**
- * Delivers the specified message to the specified queue. A 'deliverFirst' flag may be set if the message is a
- * redelivery, and should be placed on the front of the queue.
+ * Delivers the specified message to the specified queue.
*
* <p/>This is an 'enqueue' operation.
*
- * @param entry The message to deliver, and the queue to deliver to.
- * @param deliverFirst <tt>true</tt> to place the message on the front of the queue for redelivery, <tt>false</tt>
- * for normal FIFO message ordering.
- *
+ * @param queue
+ * @param message The message to deliver
* @throws AMQException If the message cannot be delivered for any reason.
*/
- void deliver(QueueEntry entry, boolean deliverFirst) throws AMQException;
+ void deliver(final AMQQueue queue, AMQMessage message) throws AMQException;
+
+ /**
+ * Requeues the specified message entry (message queue pair)
+ *
+ *
+ * @param queueEntry The message,queue pair
+ *
+ * @throws AMQException If the message cannot be delivered for any reason.
+ */
+ void requeue(QueueEntry queueEntry) throws AMQException;
+
/**
* Acknowledges a message or many messages as delivered. All messages up to a specified one, may be acknowledged by
diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/NullApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/util/NullApplicationRegistry.java
index 0acfa84f31..ee5f9d5e88 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/util/NullApplicationRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/util/NullApplicationRegistry.java
@@ -42,19 +42,6 @@ import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
public class NullApplicationRegistry extends ApplicationRegistry
{
- private ManagedObjectRegistry _managedObjectRegistry;
-
- private AuthenticationManager _authenticationManager;
-
- private VirtualHostRegistry _virtualHostRegistry;
-
- private ACLPlugin _accessManager;
-
- private PrincipalDatabaseManager _databaseManager;
-
- private PluginManager _pluginManager;
-
-
public NullApplicationRegistry()
{
super(new MapConfiguration(new HashMap()));
@@ -62,6 +49,8 @@ public class NullApplicationRegistry extends ApplicationRegistry
public void initialise() throws Exception
{
+ _logger.info("Initialising NullApplicationRegistry");
+
_configuration.addProperty("store.class", "org.apache.qpid.server.store.MemoryMessageStore");
Properties users = new Properties();
@@ -84,47 +73,11 @@ public class NullApplicationRegistry extends ApplicationRegistry
}
- public Configuration getConfiguration()
- {
- return _configuration;
- }
-
-
- public ManagedObjectRegistry getManagedObjectRegistry()
- {
- return _managedObjectRegistry;
- }
-
- public PrincipalDatabaseManager getDatabaseManager()
- {
- return _databaseManager;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
public Collection<String> getVirtualHostNames()
{
String[] hosts = {"test"};
return Arrays.asList(hosts);
}
-
- public VirtualHostRegistry getVirtualHostRegistry()
- {
- return _virtualHostRegistry;
- }
-
- public ACLPlugin getAccessManager()
- {
- return _accessManager;
- }
-
- public PluginManager getPluginManager()
- {
- return _pluginManager;
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
index 70a76dd8c2..85d804457e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
@@ -1,44 +1,44 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.io.IOException;
-
-import org.apache.qpid.server.management.MBeanAttribute;
-
-/**
- * The management interface exposed to allow management of an Exchange.
- * @version 0.1
- */
-public interface ManagedVirtualHost
-{
- static final String TYPE = "VirtualHost";
-
- /**
- * Returns the name of the managed virtualHost.
- * @return the name of the exchange.
- * @throws java.io.IOException
- */
- @MBeanAttribute(name="Name", description= TYPE + " Name")
- String getName() throws IOException;
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.virtualhost;
+
+import java.io.IOException;
+
+import org.apache.qpid.server.management.MBeanAttribute;
+
+/**
+ * The management interface exposed to allow management of an Exchange.
+ * @version 0.1
+ */
+public interface ManagedVirtualHost
+{
+ static final String TYPE = "VirtualHost";
+
+ /**
+ * Returns the name of the managed virtualHost.
+ * @return the name of the exchange.
+ * @throws java.io.IOException
+ */
+ @MBeanAttribute(name="Name", description= TYPE + " Name")
+ String getName() throws IOException;
+
+
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index 90dc7432b2..b25a56344e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -26,6 +26,8 @@ import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.log4j.Logger;
import org.apache.qpid.server.AMQBrokerManagerMBean;
+import org.apache.qpid.server.connection.ConnectionRegistry;
+import org.apache.qpid.server.connection.IConnectionRegistry;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.security.access.ACLManager;
import org.apache.qpid.server.security.access.Accessable;
@@ -55,6 +57,8 @@ public class VirtualHost implements Accessable
private final String _name;
+ private ConnectionRegistry _connectionRegistry;
+
private QueueRegistry _queueRegistry;
private ExchangeRegistry _exchangeRegistry;
@@ -71,10 +75,11 @@ public class VirtualHost implements Accessable
private ACLPlugin _accessManager;
- private Timer _houseKeepingTimer;
-
+ private final Timer _houseKeepingTimer;
+
private static final long DEFAULT_HOUSEKEEPING_PERIOD = 30000L;
-
+
+
public void setAccessableName(String name)
{
_logger.warn("Setting Accessable Name for VirualHost is not allowed. ("
@@ -86,6 +91,10 @@ public class VirtualHost implements Accessable
return _name;
}
+ public IConnectionRegistry getConnectionRegistry()
+ {
+ return _connectionRegistry;
+ }
/**
* Abstract MBean class. This has some of the methods implemented from management intrerface for exchanges. Any
@@ -140,12 +149,18 @@ public class VirtualHost implements Accessable
public VirtualHost(String name, Configuration hostConfig, MessageStore store) throws Exception
{
+ if (name == null || name.length() == 0)
+ {
+ throw new IllegalArgumentException("Illegal name (" + name + ") for virtualhost.");
+ }
+
_name = name;
_virtualHostMBean = new VirtualHostMBean();
- // This isn't needed to be registered
- //_virtualHostMBean.register();
+ _connectionRegistry = new ConnectionRegistry(this);
+
+ _houseKeepingTimer = new Timer("Queue-housekeeping-"+name, true);
_queueRegistry = new DefaultQueueRegistry(this);
_exchangeFactory = new DefaultExchangeFactory(this);
_exchangeFactory.initialise(hostConfig);
@@ -172,25 +187,22 @@ public class VirtualHost implements Accessable
_brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
_brokerMBean.register();
-
- _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true);
-
initialiseHouseKeeping(hostConfig);
}
private void initialiseHouseKeeping(final Configuration hostConfig)
{
-
+
long period = hostConfig.getLong("housekeeping.expiredMessageCheckPeriod", DEFAULT_HOUSEKEEPING_PERIOD);
-
+
/* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */
- if (period != 0L)
+ if(period != 0L)
{
class RemoveExpiredMessagesTask extends TimerTask
{
public void run()
{
- for (AMQQueue q : _queueRegistry.getQueues())
+ for(AMQQueue q : _queueRegistry.getQueues())
{
try
@@ -199,7 +211,7 @@ public class VirtualHost implements Accessable
}
catch (AMQException e)
{
- _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e);
+ _logger.error("Exception in housekeeping for queue: " + q.getName().toString(),e);
throw new RuntimeException(e);
}
}
@@ -207,11 +219,11 @@ public class VirtualHost implements Accessable
}
_houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(),
- period / 2,
- period);
+ period/2,
+ period);
}
}
-
+
private void initialiseMessageStore(Configuration config) throws Exception
{
String messageStoreClass = config.getString("store.class");
@@ -285,14 +297,20 @@ public class VirtualHost implements Accessable
public ACLPlugin getAccessManager()
{
return _accessManager;
- }
+ }
public void close() throws Exception
{
+ //Stop Housekeeping
if (_houseKeepingTimer != null)
{
_houseKeepingTimer.cancel();
}
+
+ //Stop Connections
+ _connectionRegistry.close();
+
+ //Close MessageStore
if (_messageStore != null)
{
_messageStore.close();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
index 9b1619c609..27917fac8a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
@@ -1,70 +1,70 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-
-public class VirtualHostRegistry
-{
- private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
-
-
- private String _defaultVirtualHostName;
-
- public synchronized void registerVirtualHost(VirtualHost host) throws Exception
- {
- if(_registry.containsKey(host.getName()))
- {
- throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
- }
- _registry.put(host.getName(),host);
- }
-
- public VirtualHost getVirtualHost(String name)
- {
- if(name == null || name.trim().length() == 0 )
- {
- name = getDefaultVirtualHostName();
- }
-
- return _registry.get(name);
- }
-
- private String getDefaultVirtualHostName()
- {
- return _defaultVirtualHostName;
- }
-
- public void setDefaultVirtualHostName(String defaultVirtualHostName)
- {
- _defaultVirtualHostName = defaultVirtualHostName;
- }
-
-
- public Collection<VirtualHost> getVirtualHosts()
- {
- return new ArrayList<VirtualHost>(_registry.values());
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.virtualhost;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+public class VirtualHostRegistry
+{
+ private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
+
+
+ private String _defaultVirtualHostName;
+
+ public synchronized void registerVirtualHost(VirtualHost host) throws Exception
+ {
+ if(_registry.containsKey(host.getName()))
+ {
+ throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
+ }
+ _registry.put(host.getName(),host);
+ }
+
+ public VirtualHost getVirtualHost(String name)
+ {
+ if(name == null || name.trim().length() == 0 )
+ {
+ name = getDefaultVirtualHostName();
+ }
+
+ return _registry.get(name);
+ }
+
+ private String getDefaultVirtualHostName()
+ {
+ return _defaultVirtualHostName;
+ }
+
+ public void setDefaultVirtualHostName(String defaultVirtualHostName)
+ {
+ _defaultVirtualHostName = defaultVirtualHostName;
+ }
+
+
+ public Collection<VirtualHost> getVirtualHosts()
+ {
+ return new ArrayList<VirtualHost>(_registry.values());
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
index edc900f401..faa7b85d58 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
@@ -25,11 +25,11 @@ import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.configuration.Configuration;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.tools.messagestore.commands.Clear;
import org.apache.qpid.tools.messagestore.commands.Command;
import org.apache.qpid.tools.messagestore.commands.Copy;
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
index a5b3a87616..0869d9a497 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java
@@ -20,8 +20,8 @@
*/
package org.apache.qpid.tools.messagestore.commands;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
+import org.apache.qpid.server.queue.AMQQueue;
public class Copy extends Move
{
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
index 218d5f04ed..731f6140f9 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Dump.java
@@ -24,6 +24,7 @@ import org.apache.commons.codec.binary.Hex;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntryImpl;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import org.apache.qpid.tools.utils.Console;
@@ -255,7 +256,7 @@ public class Dump extends Show
String title, boolean routing, boolean headers, boolean messageHeaders)
{
List<QueueEntry> single = new LinkedList<QueueEntry>();
- single.add(new QueueEntry(null,msg));
+ single.add(new QueueEntryImpl(null,msg, Long.MIN_VALUE));
List<List> routingData = super.createMessageData(null, single, headers, routing, messageHeaders);
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
index 7e21253fab..a8dd58ca83 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java
@@ -21,7 +21,7 @@
package org.apache.qpid.tools.messagestore.commands;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntryImpl;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.StoreContext;
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
index f187e26593..5e99997863 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Purge.java
@@ -20,9 +20,8 @@
*/
package org.apache.qpid.tools.messagestore.commands;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
+import org.apache.qpid.server.queue.AMQQueue;
public class Purge extends Move
{
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Select.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Select.java
index fd7d4c3f13..ff59568374 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Select.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Select.java
@@ -22,9 +22,9 @@ package org.apache.qpid.tools.messagestore.commands;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
import java.util.LinkedList;
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
index a6dccf0f36..2fa017fc64 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
@@ -26,6 +26,7 @@ import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.QueueEntryImpl;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.tools.messagestore.MessageStoreTool;
@@ -33,7 +34,6 @@ import org.apache.qpid.tools.utils.Console;
import java.util.LinkedList;
import java.util.List;
-import java.util.StringTokenizer;
public class Show extends AbstractCommand
{
diff --git a/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java b/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java
new file mode 100644
index 0000000000..9ef4af2932
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java
@@ -0,0 +1,120 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.ack;
+
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+
+import java.util.List;
+
+public class AcknowledgeTest extends InternalBrokerBaseCase
+{
+
+ public void testTransactionalSingleAck() throws AMQException
+ {
+ _channel.setLocalTransactional();
+ runMessageAck(1, 1, 1, false, 0);
+ }
+
+ public void testTransactionalMultiAck() throws AMQException
+ {
+ _channel.setLocalTransactional();
+ runMessageAck(10, 1, 5, true, 5);
+ }
+
+ public void testTransactionalAckAll() throws AMQException
+ {
+ _channel.setLocalTransactional();
+ runMessageAck(10, 1, 0, true, 0);
+ }
+
+ public void testNonTransactionalSingleAck() throws AMQException
+ {
+ runMessageAck(1, 1, 1, false, 0);
+ }
+
+ public void testNonTransactionalMultiAck() throws AMQException
+ {
+ runMessageAck(10, 1, 5, true, 5);
+ }
+
+ public void testNonTransactionalAckAll() throws AMQException
+ {
+ runMessageAck(10, 1, 0, true, 0);
+ }
+
+ protected void runMessageAck(int sendMessageCount, long firstDeliveryTag, long acknowledgeDeliveryTag, boolean acknowldegeMultiple, int remainingUnackedMessages) throws AMQException
+ {
+ //Check store is empty
+ checkStoreContents(0);
+
+ //Send required messsages to the queue
+ publishMessages(_session, _channel, sendMessageCount);
+
+ if (_channel.isTransactional())
+ {
+ _channel.commit();
+ }
+
+ //Ensure they are stored
+ checkStoreContents(sendMessageCount);
+
+ //Check that there are no unacked messages
+ assertEquals("Channel should have no unacked msgs ", 0, _channel.getUnacknowledgedMessageMap().size());
+
+ //Subscribe to the queue
+ AMQShortString subscriber = subscribe(_session, _channel, _queue);
+
+ _queue.deliverAsync();
+
+ //Wait for the messages to be delivered
+ _session.awaitDelivery(sendMessageCount);
+
+ //Check that they are all waiting to be acknoledged
+ assertEquals("Channel should have unacked msgs", sendMessageCount, _channel.getUnacknowledgedMessageMap().size());
+
+ List<InternalTestProtocolSession.DeliveryPair> messages = _session.getDelivers(_channel.getChannelId(), subscriber, sendMessageCount);
+
+ //Double check we received the right number of messages
+ assertEquals(sendMessageCount, messages.size());
+
+ //Check that the first message has the expected deliveryTag
+ assertEquals("First message does not have expected deliveryTag", firstDeliveryTag, messages.get(0).getDeliveryTag());
+
+ //Send required Acknowledgement
+ _channel.acknowledgeMessage(acknowledgeDeliveryTag, acknowldegeMultiple);
+
+ if (_channel.isTransactional())
+ {
+ _channel.commit();
+ }
+
+ // Check Remaining Acknowledgements
+ assertEquals("Channel unacked msgs count incorrect", remainingUnackedMessages, _channel.getUnacknowledgedMessageMap().size());
+
+ //Check store contents are also correct.
+ checkStoreContents(remainingUnackedMessages);
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java
index 2898cb38a6..a592c9353a 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/DestWildExchangeTest.java
@@ -22,9 +22,7 @@ package org.apache.qpid.server.exchange;
import junit.framework.TestCase;
import junit.framework.Assert;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.MessageHandleFactory;
+import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.txn.NonTransactionalContext;
@@ -33,6 +31,7 @@ import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
@@ -43,57 +42,51 @@ import java.util.LinkedList;
public class DestWildExchangeTest extends TestCase
{
- DestWildExchange _exchange;
+ TopicExchange _exchange;
VirtualHost _vhost;
MessageStore _store;
StoreContext _context;
+ InternalTestProtocolSession _protocolSession;
+
public void setUp() throws AMQException
{
- _exchange = new DestWildExchange();
+ _exchange = new TopicExchange();
_vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next();
_store = new MemoryMessageStore();
_context = new StoreContext();
+ _protocolSession = new InternalTestProtocolSession();
}
public void testNoRoute() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a*#b"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*.#.b"), queue, null);
MessagePublishInfo info = new PublishInfo(new AMQShortString("a.b"));
- AMQMessage message = new AMQMessage(0L, info, null);
+ IncomingMessage message = new IncomingMessage(0L, info, null, _protocolSession);
- try
- {
- _exchange.route(message);
- fail("Message has no route and shouldn't be routed");
- }
- catch (NoRouteException nre)
- {
- //normal
- }
+ _exchange.route(message);
Assert.assertEquals(0, queue.getMessageCount());
}
public void testDirectMatch() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("ab"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("ab"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.b"), queue, null);
- AMQMessage message = createMessage("a.b");
+ IncomingMessage message = createMessage("a.b");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -102,7 +95,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -112,8 +105,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has no route and should fail to be routed");
}
catch (AMQException nre)
@@ -126,16 +118,15 @@ public class DestWildExchangeTest extends TestCase
public void testStarMatch() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a*"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*"), queue, null);
- AMQMessage message = createMessage("a.b");
+ IncomingMessage message = createMessage("a.b");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -144,7 +135,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -154,8 +145,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -164,7 +154,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -174,8 +164,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has no route and should fail to be routed");
}
catch (AMQException nre)
@@ -187,16 +176,15 @@ public class DestWildExchangeTest extends TestCase
public void testHashMatch() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a#"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.#"), queue, null);
- AMQMessage message = createMessage("a.b.c");
+ IncomingMessage message = createMessage("a.b.c");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -205,7 +193,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -215,8 +203,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -225,7 +212,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -235,8 +222,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -245,7 +231,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -254,8 +240,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -264,7 +249,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -274,8 +259,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has no route and should fail to be routed");
}
catch (AMQException nre)
@@ -288,16 +272,15 @@ public class DestWildExchangeTest extends TestCase
public void testMidHash() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*.#.b"), queue, null);
- AMQMessage message = createMessage("a.c.d.b");
+ IncomingMessage message = createMessage("a.c.d.b");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -306,7 +289,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -315,8 +298,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -325,7 +307,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -334,16 +316,15 @@ public class DestWildExchangeTest extends TestCase
public void testMatchafterHash() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a#"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*.#.b.c"), queue, null);
- AMQMessage message = createMessage("a.c.b.b");
+ IncomingMessage message = createMessage("a.c.b.b");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -357,8 +338,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -367,7 +347,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -376,8 +356,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -390,8 +369,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -401,7 +379,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -411,16 +389,15 @@ public class DestWildExchangeTest extends TestCase
public void testHashAfterHash() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a#"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.*.#.b.c.#.d"), queue, null);
- AMQMessage message = createMessage("a.c.b.b.c");
+ IncomingMessage message = createMessage("a.c.b.b.c");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -434,8 +411,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -444,7 +420,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -453,16 +429,15 @@ public class DestWildExchangeTest extends TestCase
public void testHashHash() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a#"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.#.*.#.d"), queue, null);
- AMQMessage message = createMessage("a.c.b.b.c");
+ IncomingMessage message = createMessage("a.c.b.b.c");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -475,8 +450,7 @@ public class DestWildExchangeTest extends TestCase
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
}
catch (AMQException nre)
{
@@ -485,7 +459,7 @@ public class DestWildExchangeTest extends TestCase
Assert.assertEquals(1, queue.getMessageCount());
- Assert.assertEquals("Wrong message recevied", message, queue.getMessagesOnTheQueue().get(0).getMessage());
+ Assert.assertEquals("Wrong message recevied", (Object) message.getMessageId(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageId());
queue.deleteMessageFromTop(_context);
Assert.assertEquals(0, queue.getMessageCount());
@@ -494,16 +468,15 @@ public class DestWildExchangeTest extends TestCase
public void testSubMatchFails() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.b.c.d"), queue, null);
- AMQMessage message = createMessage("a.b.c");
+ IncomingMessage message = createMessage("a.b.c");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -514,18 +487,25 @@ public class DestWildExchangeTest extends TestCase
}
+ private void routeMessage(final IncomingMessage message)
+ throws AMQException
+ {
+ _exchange.route(message);
+ message.routingComplete(_store, new MessageHandleFactory());
+ message.deliverToQueues();
+ }
+
public void testMoreRouting() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.b"), queue, null);
- AMQMessage message = createMessage("a.b.c");
+ IncomingMessage message = createMessage("a.b.c");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -538,16 +518,15 @@ public class DestWildExchangeTest extends TestCase
public void testMoreQueue() throws AMQException
{
- AMQQueue queue = new AMQQueue(new AMQShortString("a"), false, null, false, _vhost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, _vhost, null);
_exchange.registerQueue(new AMQShortString("a.b"), queue, null);
- AMQMessage message = createMessage("a");
+ IncomingMessage message = createMessage("a");
try
{
- _exchange.route(message);
- message.routingComplete(_store, _context, new MessageHandleFactory());
+ routeMessage(message);
fail("Message has route and should not be routed");
}
catch (AMQException nre)
@@ -558,7 +537,7 @@ public class DestWildExchangeTest extends TestCase
}
- private AMQMessage createMessage(String s) throws AMQException
+ private IncomingMessage createMessage(String s) throws AMQException
{
MessagePublishInfo info = new PublishInfo(new AMQShortString(s));
@@ -566,8 +545,9 @@ public class DestWildExchangeTest extends TestCase
new LinkedList<RequiredDeliveryException>()
);
- AMQMessage message = new AMQMessage(0L, info, trancontext);
- message.setContentHeaderBody(new ContentHeaderBody());
+ IncomingMessage message = new IncomingMessage(0L, info, trancontext,_protocolSession);
+ message.setContentHeaderBody( new ContentHeaderBody());
+
return message;
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
index 18d8592817..2a2bc72950 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
@@ -21,8 +21,9 @@
package org.apache.qpid.server.exchange;
import junit.framework.TestCase;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.management.ManagedObject;
@@ -30,7 +31,6 @@ import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import java.util.ArrayList;
@@ -50,7 +50,7 @@ public class ExchangeMBeanTest extends TestCase
public void testDirectExchangeMBean() throws Exception
{
- DestNameExchange exchange = new DestNameExchange();
+ DirectExchange exchange = new DirectExchange();
exchange.initialise(_virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -77,7 +77,7 @@ public class ExchangeMBeanTest extends TestCase
public void testTopicExchangeMBean() throws Exception
{
- DestWildExchange exchange = new DestWildExchange();
+ TopicExchange exchange = new TopicExchange();
exchange.initialise(_virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true);
ManagedObject managedObj = exchange.getManagedObject();
ManagedExchange mbean = (ManagedExchange)managedObj;
@@ -132,7 +132,8 @@ public class ExchangeMBeanTest extends TestCase
IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
_virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
_queueRegistry = _virtualHost.getQueueRegistry();
- _queue = new AMQQueue(new AMQShortString("testQueue"), false, new AMQShortString("ExchangeMBeanTest"), false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("ExchangeMBeanTest"), false, _virtualHost,
+ null);
_queueRegistry.registerQueue(_queue);
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
new file mode 100644
index 0000000000..51012bc776
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java
@@ -0,0 +1,173 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.codec.AMQCodecFactory;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.AMQChannel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class InternalTestProtocolSession extends AMQMinaProtocolSession implements ProtocolOutputConverter
+{
+ // ChannelID(LIST) -> LinkedList<Pair>
+ final Map<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>> _channelDelivers;
+ private AtomicInteger _deliveryCount = new AtomicInteger(0);
+
+ public InternalTestProtocolSession() throws AMQException
+ {
+ super(new TestIoSession(),
+ ApplicationRegistry.getInstance().getVirtualHostRegistry(),
+ new AMQCodecFactory(true));
+
+ _channelDelivers = new HashMap<Integer, Map<AMQShortString, LinkedList<DeliveryPair>>>();
+
+ }
+
+ public ProtocolOutputConverter getProtocolOutputConverter()
+ {
+ return this;
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return (byte) 8;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return (byte) 0;
+ }
+
+ // ***
+
+ public List<DeliveryPair> getDelivers(int channelId, AMQShortString consumerTag, int count)
+ {
+ synchronized (_channelDelivers)
+ {
+ List<DeliveryPair> msgs = _channelDelivers.get(channelId).get(consumerTag).subList(0, count);
+
+ List<DeliveryPair> response = new ArrayList<DeliveryPair>(msgs);
+
+ //Remove the msgs from the receivedList.
+ msgs.clear();
+
+ return response;
+ }
+ }
+
+ // *** ProtocolOutputConverter Implementation
+ public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ {
+ }
+
+ public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
+ {
+ }
+
+ public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException
+ {
+ _deliveryCount.incrementAndGet();
+
+ synchronized (_channelDelivers)
+ {
+ Map<AMQShortString, LinkedList<DeliveryPair>> consumers = _channelDelivers.get(channelId);
+
+ if (consumers == null)
+ {
+ consumers = new HashMap<AMQShortString, LinkedList<DeliveryPair>>();
+ _channelDelivers.put(channelId, consumers);
+ }
+
+ LinkedList<DeliveryPair> consumerDelivers = consumers.get(consumerTag);
+
+ if (consumerDelivers == null)
+ {
+ consumerDelivers = new LinkedList<DeliveryPair>();
+ consumers.put(consumerTag, consumerDelivers);
+ }
+
+ consumerDelivers.add(new DeliveryPair(deliveryTag, message));
+ }
+ }
+
+ public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+ }
+
+ public void awaitDelivery(int msgs)
+ {
+ while (msgs > _deliveryCount.get())
+ {
+ try
+ {
+ Thread.sleep(100);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public class DeliveryPair
+ {
+ private long _deliveryTag;
+ private AMQMessage _message;
+
+ public DeliveryPair(long deliveryTag, AMQMessage message)
+ {
+ _deliveryTag = deliveryTag;
+ _message = message;
+ }
+
+ public AMQMessage getMessage()
+ {
+ return _message;
+ }
+
+ public long getDeliveryTag()
+ {
+ return _deliveryTag;
+ }
+ }
+
+ public boolean isClosed()
+ {
+ return _closed;
+ }
+
+ public void closeProtocolSession(boolean waitLast)
+ {
+ // Override as we don't have a real IOSession to close.
+ // The alternative is to fully implement the TestIOSession to return a CloseFuture from close();
+ // Then the AMQMinaProtocolSession can join on the returning future without a NPE.
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/TestMinaProtocolSession.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/TestMinaProtocolSession.java
deleted file mode 100644
index 0c0d8f471e..0000000000
--- a/java/broker/src/test/java/org/apache/qpid/server/protocol/TestMinaProtocolSession.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.codec.AMQCodecFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
-
-public class TestMinaProtocolSession extends AMQMinaProtocolSession
-{
- public TestMinaProtocolSession() throws AMQException
- {
- super(new TestIoSession(),
- ApplicationRegistry.getInstance().getVirtualHostRegistry(),
- new AMQCodecFactory(true));
- }
-
- public ProtocolOutputConverter getProtocolOutputConverter()
- {
- return ProtocolOutputConverterRegistry.getConverter(this);
- }
-
- public byte getProtocolMajorVersion()
- {
- return (byte)8;
- }
-
- public byte getProtocolMinorVersion()
- {
- return (byte)0;
- }
-}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
index 65db2a6425..dca6d9f613 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
@@ -32,18 +32,25 @@ import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.RequiredDeliveryException;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.TestMinaProtocolSession;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.protocol.AMQMinaProtocolSession;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.mina.common.ByteBuffer;
import javax.management.Notification;
+
+import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.Collections;
/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */
public class AMQQueueAlertTest extends TestCase
-{
+{
private final static long MAX_MESSAGE_COUNT = 50;
private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec
private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB
@@ -51,13 +58,14 @@ public class AMQQueueAlertTest extends TestCase
private AMQQueue _queue;
private AMQQueueMBean _queueMBean;
private VirtualHost _virtualHost;
- private AMQMinaProtocolSession protocolSession = null;
+ private AMQMinaProtocolSession _protocolSession;
private MessageStore _messageStore = new MemoryMessageStore();
private StoreContext _storeContext = new StoreContext();
private TransactionalContext _transactionalContext = new NonTransactionalContext(_messageStore, _storeContext,
null,
new LinkedList<RequiredDeliveryException>()
);
+ private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
/**
* Tests if the alert gets thrown when message count increases the threshold limit
@@ -66,8 +74,9 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageCountAlert() throws Exception
{
- _queue = new AMQQueue(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"),
- false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"),
+ false, _virtualHost,
+ null);
_queueMBean = (AMQQueueMBean) _queue.getManagedObject();
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
@@ -89,8 +98,9 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageSizeAlert() throws Exception
{
- _queue = new AMQQueue(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"),
- false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"),
+ false, _virtualHost,
+ null);
_queueMBean = (AMQQueueMBean) _queue.getManagedObject();
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
_queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE);
@@ -114,8 +124,9 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testQueueDepthAlertNoSubscriber() throws Exception
{
- _queue = new AMQQueue(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"),
- false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"),
+ false, _virtualHost,
+ null);
_queueMBean = (AMQQueueMBean) _queue.getManagedObject();
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
_queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH);
@@ -142,8 +153,9 @@ public class AMQQueueAlertTest extends TestCase
*/
public void testMessageAgeAlert() throws Exception
{
- _queue = new AMQQueue(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"),
- false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"),
+ false, _virtualHost,
+ null);
_queueMBean = (AMQQueueMBean) _queue.getManagedObject();
_queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT);
_queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE);
@@ -167,18 +179,23 @@ public class AMQQueueAlertTest extends TestCase
This test sends some messages to the queue with subscribers needing message to be acknowledged.
The messages will not be acknowledged and will be required twice. Why we are checking this is because
the bug reported said that the queueDepth keeps increasing when messages are requeued.
+ // TODO - queue depth now includes unacknowledged messages so does not go down when messages are delivered
+
The QueueDepth should decrease when messages are delivered from the queue (QPID-408)
*/
public void testQueueDepthAlertWithSubscribers() throws Exception
{
- protocolSession = new TestMinaProtocolSession();
- AMQChannel channel = new AMQChannel(protocolSession, 2, _messageStore);
- protocolSession.addChannel(channel);
+ _protocolSession = new InternalTestProtocolSession();
+ AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
+ _protocolSession.addChannel(channel);
// Create queue
_queue = getNewQueue();
- _queue.registerProtocolSession(protocolSession, channel.getChannelId(),
- new AMQShortString("consumer_tag"), true, null, false, false);
+ Subscription subscription =
+ SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), _protocolSession, new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
+
+ _queue.registerSubscription(
+ subscription, false);
_queueMBean = (AMQQueueMBean) _queue.getManagedObject();
_queueMBean.setMaximumMessageCount(9999l); // Set a high value, because this is not being tested
@@ -191,13 +208,13 @@ public class AMQQueueAlertTest extends TestCase
// Check queueDepth. There should be no messages on the queue and as the subscriber is listening
// so there should be no Queue_Deoth alert raised
- assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
+ assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
Notification lastNotification = _queueMBean.getLastNotification();
- assertNull(lastNotification);
+// assertNull(lastNotification);
// Kill the subscriber and check for the queue depth values.
// Messages are unacknowledged, so those should get requeued. All messages should be on the Queue
- _queue.unregisterProtocolSession(protocolSession, channel.getChannelId(), new AMQShortString("consumer_tag"));
+ _queue.unregisterSubscription(subscription);
channel.requeue();
assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
@@ -209,29 +226,32 @@ public class AMQQueueAlertTest extends TestCase
// Connect a consumer again and check QueueDepth values. The queue should get emptied.
// Messages will get delivered but still are unacknowledged.
- _queue.registerProtocolSession(protocolSession, channel.getChannelId(),
- new AMQShortString("consumer_tag"), true, null, false, false);
- _queue.deliverAsync();
- while (_queue.getMessageCount() != 0)
+ Subscription subscription2 =
+ SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), _protocolSession, new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager());
+
+ _queue.registerSubscription(
+ subscription2, false);
+
+ while (_queue.getUndeliveredMessageCount()!= 0)
{
Thread.sleep(100);
}
- assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
+// assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
// Kill the subscriber again. Now those messages should get requeued again. Check if the queue depth
// value is correct.
- _queue.unregisterProtocolSession(protocolSession, channel.getChannelId(), new AMQShortString("consumer_tag"));
+ _queue.unregisterSubscription(subscription2);
channel.requeue();
assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth()));
- protocolSession.closeSession();
+ _protocolSession.closeSession();
// Check the clear queue
_queueMBean.clearQueue();
assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth()));
}
- protected AMQMessage message(final boolean immediate, long size) throws AMQException
+ protected IncomingMessage message(final boolean immediate, long size) throws AMQException
{
MessagePublishInfo publish = new MessagePublishInfo()
{
@@ -264,9 +284,9 @@ public class AMQQueueAlertTest extends TestCase
ContentHeaderBody contentHeaderBody = new ContentHeaderBody();
contentHeaderBody.bodySize = size; // in bytes
- AMQMessage message = new AMQMessage(_messageStore.getNewMessageId(), publish, _transactionalContext);
+ IncomingMessage message = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession);
message.setContentHeaderBody(contentHeaderBody);
- message.setPublisher(protocolSession);
+
return message;
}
@@ -276,30 +296,54 @@ public class AMQQueueAlertTest extends TestCase
super.setUp();
IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
_virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
+ _protocolSession = new InternalTestProtocolSession();
+
}
- private void sendMessages(long messageCount, long size) throws AMQException
+ private void sendMessages(long messageCount, final long size) throws AMQException
{
- AMQMessage[] messages = new AMQMessage[(int) messageCount];
+ IncomingMessage[] messages = new IncomingMessage[(int) messageCount];
for (int i = 0; i < messages.length; i++)
{
messages[i] = message(false, size);
- messages[i].enqueue(_queue);
- messages[i].routingComplete(_messageStore, _storeContext, new MessageHandleFactory());
+ ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
+ qs.add(_queue);
+ messages[i].enqueue(qs);
+ messages[i].routingComplete(_messageStore, new MessageHandleFactory());
+
}
for (int i = 0; i < messageCount; i++)
{
- _queue.process(_storeContext, new QueueEntry(_queue,messages[i]), false);
+ messages[i].addContentBodyFrame(new ContentChunk(){
+
+ ByteBuffer _data = ByteBuffer.allocate((int)size);
+
+ public int getSize()
+ {
+ return (int) size;
+ }
+
+ public ByteBuffer getData()
+ {
+ return _data;
+ }
+
+ public void reduceToFit()
+ {
+
+ }
+ });
+ messages[i].deliverToQueues();
}
}
private AMQQueue getNewQueue() throws AMQException
{
- return new AMQQueue(new AMQShortString("testQueue" + Math.random()),
+ return AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue" + Math.random()),
false,
new AMQShortString("AMQueueAlertTest"),
false,
- _virtualHost);
+ _virtualHost, null);
}
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
index 9b874d63e8..50bee71d59 100644
--- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java
@@ -27,10 +27,14 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.protocol.TestMinaProtocolSession;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactory;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -43,7 +47,10 @@ import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.mina.common.ByteBuffer;
import javax.management.JMException;
+
+import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.Collections;
/**
* Test class to test AMQQueueMBean attribtues and operations
@@ -58,6 +65,7 @@ public class AMQQueueMBeanTest extends TestCase
private TransactionalContext _transactionalContext;
private VirtualHost _virtualHost;
private AMQProtocolSession _protocolSession;
+ private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE;
public void testMessageCountTransient() throws Exception
{
@@ -73,7 +81,7 @@ public class AMQQueueMBeanTest extends TestCase
assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
_queueMBean.clearQueue();
- assertTrue(_queueMBean.getMessageCount() == 0);
+ assertEquals(0,(int)_queueMBean.getMessageCount());
assertTrue(_queueMBean.getReceivedMessageCount() == messageCount);
//Ensure that the data has been removed from the Store
@@ -116,27 +124,30 @@ public class AMQQueueMBeanTest extends TestCase
public void testConsumerCount() throws AMQException
{
- SubscriptionManager mgr = _queue.getSubscribers();
- assertFalse(mgr.hasActiveSubscribers());
+
+ assertTrue(_queue.getActiveConsumerCount() == 0);
assertTrue(_queueMBean.getActiveConsumerCount() == 0);
- TestMinaProtocolSession protocolSession = new TestMinaProtocolSession();
+ InternalTestProtocolSession protocolSession = new InternalTestProtocolSession();
AMQChannel channel = new AMQChannel(protocolSession, 1, _messageStore);
protocolSession.addChannel(channel);
- _queue.registerProtocolSession(protocolSession, 1, new AMQShortString("test"), false, null, false, false);
- assertTrue(_queueMBean.getActiveConsumerCount() == 1);
+ Subscription subscription =
+ SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager());
+
+ _queue.registerSubscription(subscription, false);
+ assertEquals(1,(int)_queueMBean.getActiveConsumerCount());
- SubscriptionSet _subscribers = (SubscriptionSet) mgr;
- SubscriptionFactory subscriptionFactory = new SubscriptionImpl.Factory();
+
+ SubscriptionFactory subscriptionFactory = SUBSCRIPTION_FACTORY;
Subscription s1 = subscriptionFactory.createSubscription(channel.getChannelId(),
protocolSession,
new AMQShortString("S1"),
false,
null,
true,
- _queue);
+ channel.getCreditManager());
Subscription s2 = subscriptionFactory.createSubscription(channel.getChannelId(),
protocolSession,
@@ -144,14 +155,14 @@ public class AMQQueueMBeanTest extends TestCase
false,
null,
true,
- _queue);
- _subscribers.addSubscriber(s1);
- _subscribers.addSubscriber(s2);
+ channel.getCreditManager());
+ _queue.registerSubscription(s1,false);
+ _queue.registerSubscription(s2,false);
assertTrue(_queueMBean.getActiveConsumerCount() == 3);
assertTrue(_queueMBean.getConsumerCount() == 3);
s1.close();
- assertTrue(_queueMBean.getActiveConsumerCount() == 2);
+ assertEquals(2, (int) _queueMBean.getActiveConsumerCount());
assertTrue(_queueMBean.getConsumerCount() == 3);
}
@@ -204,13 +215,35 @@ public class AMQQueueMBeanTest extends TestCase
}
- AMQMessage msg = message(false, false);
+ IncomingMessage msg = message(false, false);
long id = msg.getMessageId();
_queue.clearQueue(_storeContext);
+ ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
+ qs.add(_queue);
+ msg.enqueue(qs);
+ msg.routingComplete(_messageStore, new MessageHandleFactory());
+
+ msg.addContentBodyFrame(new ContentChunk()
+ {
+ ByteBuffer _data = ByteBuffer.allocate((int)MESSAGE_SIZE);
+
+ public int getSize()
+ {
+ return (int) MESSAGE_SIZE;
+ }
- msg.enqueue(_queue);
- msg.routingComplete(_messageStore, _storeContext, new MessageHandleFactory());
- _queue.process(_storeContext, new QueueEntry(_queue, msg), false);
+ public ByteBuffer getData()
+ {
+ return _data;
+ }
+
+ public void reduceToFit()
+ {
+
+ }
+ });
+ msg.deliverToQueues();
+// _queue.process(_storeContext, new QueueEntry(_queue, msg), false);
_queueMBean.viewMessageContent(id);
try
{
@@ -223,7 +256,7 @@ public class AMQQueueMBeanTest extends TestCase
}
}
- private AMQMessage message(final boolean immediate, boolean persistent) throws AMQException
+ private IncomingMessage message(final boolean immediate, boolean persistent) throws AMQException
{
MessagePublishInfo publish = new MessagePublishInfo()
{
@@ -258,7 +291,10 @@ public class AMQQueueMBeanTest extends TestCase
contentHeaderBody.bodySize = MESSAGE_SIZE; // in bytes
contentHeaderBody.properties = new BasicContentHeaderProperties();
((BasicContentHeaderProperties) contentHeaderBody.properties).setDeliveryMode((byte) (persistent ? 2 : 1));
- return new AMQMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, contentHeaderBody);
+ IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publish, _transactionalContext, _protocolSession);
+ msg.setContentHeaderBody(contentHeaderBody);
+ return msg;
+
}
@Override
@@ -274,29 +310,33 @@ public class AMQQueueMBeanTest extends TestCase
new LinkedList<RequiredDeliveryException>()
);
- _queue = new AMQQueue(new AMQShortString("testQueue"), false, new AMQShortString("AMQueueMBeanTest"), false, _virtualHost);
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("AMQueueMBeanTest"), false, _virtualHost,
+ null);
_queueMBean = new AMQQueueMBean(_queue);
- _protocolSession = new TestMinaProtocolSession();
+ _protocolSession = new InternalTestProtocolSession();
}
private void sendMessages(int messageCount, boolean persistent) throws AMQException
{
for (int i = 0; i < messageCount; i++)
{
- AMQMessage currentMessage = message(false, persistent);
- currentMessage.enqueue(_queue);
+ IncomingMessage currentMessage = message(false, persistent);
+ ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
+ qs.add(_queue);
+ currentMessage.enqueue(qs);
// route header
- currentMessage.routingComplete(_messageStore, _storeContext, new MessageHandleFactory());
+ currentMessage.routingComplete(_messageStore, new MessageHandleFactory());
// Add the body so we have somthing to test later
- currentMessage.addContentBodyFrame(_storeContext,
- _protocolSession.getMethodRegistry()
+ currentMessage.addContentBodyFrame(
+ _protocolSession.getMethodRegistry()
.getProtocolVersionMethodConverter()
.convertToContentChunk(
new ContentBody(ByteBuffer.allocate((int) MESSAGE_SIZE),
MESSAGE_SIZE)));
+ currentMessage.deliverToQueues();
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
new file mode 100644
index 0000000000..c69ca507ef
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java
@@ -0,0 +1,178 @@
+package org.apache.qpid.server.queue;
+
+import java.util.List;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.txn.NonTransactionalContext;
+import org.apache.qpid.server.txn.TransactionalContext;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import junit.framework.TestCase;
+
+public class SimpleAMQQueueTest extends TestCase
+{
+
+ private SimpleAMQQueue _queue;
+ private MessageStore store = new TestableMemoryMessageStore();
+ private TransactionalContext ctx = new NonTransactionalContext(store, new StoreContext(), null, null);
+ private MessageHandleFactory factory = new MessageHandleFactory();
+
+ MessagePublishInfo info = new MessagePublishInfo()
+ {
+
+ public AMQShortString getExchange()
+ {
+ return null;
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isImmediate()
+ {
+ return false;
+ }
+
+ public boolean isMandatory()
+ {
+ return false;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return null;
+ }
+ };
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ AMQShortString qname = new AMQShortString("qname");
+ AMQShortString owner = new AMQShortString("owner");
+ _queue = new SimpleAMQQueue(qname, false, owner, false, new VirtualHost("vhost", store));
+ }
+
+ public void testGetFirstMessageId() throws Exception
+ {
+ // Create message
+ Long messageId = new Long(23);
+ AMQMessage message = new TestMessage(messageId, messageId, info, new StoreContext());
+
+ // Put message on queue
+ _queue.enqueue(null, message);
+ // Get message id
+ Long testmsgid = _queue.getMessagesOnTheQueue(1).get(0);
+
+ // Check message id
+ assertEquals("Message ID was wrong", messageId, testmsgid);
+ }
+
+ public void testGetFirstFiveMessageIds() throws Exception
+ {
+ for (int i = 0 ; i < 5; i++)
+ {
+ // Create message
+ Long messageId = new Long(i);
+ AMQMessage message = new TestMessage(messageId, messageId, info, new StoreContext());
+ // Put message on queue
+ _queue.enqueue(null, message);
+ }
+ // Get message ids
+ List<Long> msgids = _queue.getMessagesOnTheQueue(5);
+
+ // Check message id
+ for (int i = 0; i < 5; i++)
+ {
+ Long messageId = new Long(i);
+ assertEquals("Message ID was wrong", messageId, msgids.get(i));
+ }
+ }
+
+ public void testGetLastFiveMessageIds() throws Exception
+ {
+ for (int i = 0 ; i < 10; i++)
+ {
+ // Create message
+ Long messageId = new Long(i);
+ AMQMessage message = new TestMessage(messageId, messageId, info, new StoreContext());
+ // Put message on queue
+ _queue.enqueue(null, message);
+ }
+ // Get message ids
+ List<Long> msgids = _queue.getMessagesOnTheQueue(5, 5);
+
+ // Check message id
+ for (int i = 0; i < 5; i++)
+ {
+ Long messageId = new Long(i+5);
+ assertEquals("Message ID was wrong", messageId, msgids.get(i));
+ }
+ }
+
+
+ // FIXME: move this to somewhere useful
+ private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody)
+ {
+ final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
+ null,
+ false);
+ try
+ {
+ amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),
+ publishBody,
+ new ContentHeaderBody()
+ {
+ public int getSize()
+ {
+ return 1;
+ }
+ });
+ }
+ catch (AMQException e)
+ {
+ // won't happen
+ }
+
+
+ return amqMessageHandle;
+ }
+
+ public class TestMessage extends AMQMessage
+ {
+ private final long _tag;
+ private int _count;
+
+ TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext)
+ throws AMQException
+ {
+ super(createMessageHandle(messageId, publishBody), storeContext, publishBody);
+ _tag = tag;
+ }
+
+
+ public boolean incrementReference()
+ {
+ _count++;
+ return true;
+ }
+
+ public void decrementReference(StoreContext context)
+ {
+ _count--;
+ }
+
+ void assertCountEquals(int expected)
+ {
+ assertEquals("Wrong count for message with tag " + _tag, expected, _count);
+ }
+ }
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java
new file mode 100644
index 0000000000..f80413d4f8
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/SaslServerTestCase.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.security.auth.sasl;
+
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+
+import junit.framework.TestCase;
+
+public abstract class SaslServerTestCase extends TestCase
+{
+ protected SaslServer server;
+ protected String username = "u";
+ protected String password = "p";
+ protected String notpassword = "a";
+ protected PrincipalDatabase db = new TestPrincipalDatabase();
+
+ protected byte[] correctresponse;
+ protected byte[] wrongresponse;
+
+ public void testSucessfulAuth() throws SaslException
+ {
+ byte[] resp = this.server.evaluateResponse(correctresponse);
+ assertNull(resp);
+ }
+
+ public void testFailAuth()
+ {
+ boolean exceptionCaught = false;
+ try
+ {
+ byte[] resp = this.server.evaluateResponse(wrongresponse);
+ }
+ catch (SaslException e)
+ {
+ assertEquals("Authentication failed", e.getCause().getMessage());
+ exceptionCaught = true;
+ }
+ if (!exceptionCaught)
+ {
+ fail("Should have thrown SaslException");
+ }
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java
new file mode 100644
index 0000000000..a87c727a9a
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java
@@ -0,0 +1,86 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.security.auth.sasl;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.AccountNotFoundException;
+
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+
+public class TestPrincipalDatabase implements PrincipalDatabase
+{
+
+ public boolean createPrincipal(Principal principal, char[] password)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Map<String, AuthenticationProviderInitialiser> getMechanisms()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Principal getUser(String username)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List<Principal> getUsers()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setPassword(Principal principal, PasswordCallback callback) throws IOException,
+ AccountNotFoundException
+ {
+ callback.setPassword("p".toCharArray());
+ }
+
+ public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/amqplain/AMQPlainSaslServerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/amqplain/AMQPlainSaslServerTest.java
new file mode 100644
index 0000000000..6245064bf7
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/amqplain/AMQPlainSaslServerTest.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.security.auth.sasl.amqplain;
+
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
+import org.apache.qpid.server.security.auth.sasl.SaslServerTestCase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+
+public class AMQPlainSaslServerTest extends SaslServerTestCase
+{
+ protected void setUp() throws Exception
+ {
+ UsernamePasswordInitialiser handler = new AmqPlainInitialiser();
+ handler.initialise(db);
+ this.server = new AmqPlainSaslServer(handler.getCallbackHandler());
+ FieldTable table = FieldTableFactory.newFieldTable();
+ table.setString("LOGIN", username);
+ table.setString("PASSWORD", password);
+ correctresponse = table.getDataAsBytes();
+ table.setString("PASSWORD", notpassword);
+ wrongresponse = table.getDataAsBytes();
+ }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/VMBrokerSetup.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerTest.java
index e859fac4af..5dd51250dc 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/VMBrokerSetup.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerTest.java
@@ -1,4 +1,5 @@
/*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -6,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,36 +18,22 @@
* under the License.
*
*/
-package org.apache.qpid.test;
-import junit.extensions.TestSetup;
-import junit.framework.Test;
+package org.apache.qpid.server.security.auth.sasl.plain;
-import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.server.security.auth.sasl.SaslServerTestCase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
-public class VMBrokerSetup extends TestSetup
+public class PlainSaslServerTest extends SaslServerTestCase
{
- public VMBrokerSetup(Test t)
- {
- super(t);
- }
-
+
protected void setUp() throws Exception
{
- super.setUp();
- try
- {
- TransportConnection.createVMBroker(1);
- }
- catch (Exception e)
- {
- fail("Unable to create broker: " + e);
- }
- }
-
- protected void tearDown() throws Exception
- {
- TransportConnection.killVMBroker(1);
- super.tearDown();
+ UsernamePasswordInitialiser handler = new PlainInitialiser();
+ handler.initialise(db);
+ this.server = new PlainSaslServer(handler.getCallbackHandler());
+ correctresponse = new byte[]{0x0, (byte) username.charAt(0), 0x0, (byte) password.charAt(0)};
+ wrongresponse = new byte[]{0x0,(byte) username.charAt(0), 0x0, (byte) notpassword.charAt(0)};
}
+
}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreShutdownTest.java
new file mode 100644
index 0000000000..a695a67eea
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreShutdownTest.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import org.apache.qpid.server.util.InternalBrokerBaseCase;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+
+import java.util.List;
+
+public class MessageStoreShutdownTest extends InternalBrokerBaseCase
+{
+
+ public void test()
+ {
+ subscribe(_session, _channel, _queue);
+
+ try
+ {
+ publishMessages(_session, _channel, 1);
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ fail(e.getMessage());
+ }
+
+ try
+ {
+ _registry.close();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ fail(e.getMessage());
+ }
+
+ assertTrue("Session should now be closed", _session.isClosed());
+
+
+ //Test attempting to modify the broker state after session has been closed.
+
+ //The Message should have been removed from the unacked list.
+
+ //Ack Messages
+ List<InternalTestProtocolSession.DeliveryPair> list = _session.getDelivers(_channel.getChannelId(), new AMQShortString("sgen_1"), 1);
+
+ InternalTestProtocolSession.DeliveryPair pair = list.get(0);
+
+ try
+ {
+ // The message should now be requeued and so unable to ack it.
+ _channel.acknowledgeMessage(pair.getDeliveryTag(), false);
+ }
+ catch (AMQException e)
+ {
+ assertEquals("Incorrect exception thrown", "Single ack on delivery tag 1 not known for channel:1", e.getMessage());
+ }
+
+ }
+
+}
diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
new file mode 100644
index 0000000000..932486d954
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -0,0 +1,632 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import junit.framework.TestCase;
+import org.apache.qpid.server.exchange.DirectExchange;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.exchange.ExchangeType;
+import org.apache.qpid.server.exchange.TopicExchange;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.IncomingMessage;
+import org.apache.qpid.server.queue.MessageHandleFactory;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQPriorityQueue;
+import org.apache.qpid.server.queue.SimpleAMQQueue;
+import org.apache.qpid.server.queue.ExchangeBinding;
+import org.apache.qpid.server.txn.NonTransactionalContext;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.amqp_8_0.BasicConsumeBodyImpl;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * This tests the MessageStores by using the available interfaces.
+ *
+ * This test validates that Exchanges, Queues, Bindings and Messages are persisted correctly.
+ */
+public class MessageStoreTest extends TestCase
+{
+
+ private static final int DEFAULT_PRIORTY_LEVEL = 5;
+ private static final Logger _logger = LoggerFactory.getLogger(MessageStoreTest.class);
+
+ public void testMemoryMessageStore()
+ {
+
+ PropertiesConfiguration config = new PropertiesConfiguration();
+
+ config.addProperty("store.class", "org.apache.qpid.server.store.MemoryMessageStore");
+
+ runTestWithStore(config);
+ }
+
+ public void DISABLE_testDerbyMessageStore()
+ {
+ PropertiesConfiguration config = new PropertiesConfiguration();
+
+ config.addProperty("store.environment-path", "derbyDB_MST");
+ config.addProperty("store.class", "org.apache.qpid.server.store.DerbyMessageStore");
+
+ runTestWithStore(config);
+ }
+
+ private void reload(Configuration configuration)
+ {
+ if (_virtualHost != null)
+ {
+ try
+ {
+ _virtualHost.close();
+ }
+ catch (Exception e)
+ {
+ fail(e.getMessage());
+ }
+ }
+
+ try
+ {
+ _virtualHost = new VirtualHost(virtualHostName, configuration, null);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ VirtualHost _virtualHost = null;
+ String virtualHostName = "MessageStoreTest";
+
+ AMQShortString nonDurableExchangeName = new AMQShortString("MST-NonDurableDirectExchange");
+ AMQShortString directExchangeName = new AMQShortString("MST-DirectExchange");
+ AMQShortString topicExchangeName = new AMQShortString("MST-TopicExchange");
+ AMQShortString queueOwner = new AMQShortString("MST");
+
+ AMQShortString durablePriorityTopicQueueName = new AMQShortString("MST-PriorityTopicQueue-Durable");
+ AMQShortString durableTopicQueueName = new AMQShortString("MST-TopicQueue-Durable");
+ AMQShortString priorityTopicQueueName = new AMQShortString("MST-PriorityTopicQueue");
+ AMQShortString topicQueueName = new AMQShortString("MST-TopicQueue");
+
+ AMQShortString durablePriorityQueueName = new AMQShortString("MST-PriorityQueue-Durable");
+ AMQShortString durableQueueName = new AMQShortString("MST-Queue-Durable");
+ AMQShortString priorityQueueName = new AMQShortString("MST-PriorityQueue");
+ AMQShortString queueName = new AMQShortString("MST-Queue");
+
+ AMQShortString directRouting = new AMQShortString("MST-direct");
+ AMQShortString topicRouting = new AMQShortString("MST-topic");
+
+ protected void runTestWithStore(Configuration configuration)
+ {
+ //Ensure Environment Path is empty
+ cleanup(configuration);
+
+ //Load the Virtualhost with the required MessageStore
+ reload(configuration);
+
+ MessageStore messageStore = _virtualHost.getMessageStore();
+
+ createAllQueues();
+ createAllTopicQueues();
+
+ //Register Non-Durable DirectExchange
+ Exchange nonDurableExchange = createExchange(DirectExchange.TYPE, nonDurableExchangeName, false);
+ bindAllQueuesToExchange(nonDurableExchange, directRouting);
+
+ //Register DirectExchange
+ Exchange directExchange = createExchange(DirectExchange.TYPE, directExchangeName, true);
+ bindAllQueuesToExchange(directExchange, directRouting);
+
+ //Register TopicExchange
+ Exchange topicExchange = createExchange(TopicExchange.TYPE, topicExchangeName, true);
+ bindAllTopicQueuesToExchange(topicExchange, topicRouting);
+
+ //Send Message To NonDurable direct Exchange = persistent
+ sendMessageOnExchange(nonDurableExchange, directRouting, true);
+ // and non-persistent
+ sendMessageOnExchange(nonDurableExchange, directRouting, false);
+
+ //Send Message To direct Exchange = persistent
+ sendMessageOnExchange(directExchange, directRouting, true);
+ // and non-persistent
+ sendMessageOnExchange(directExchange, directRouting, false);
+
+ //Send Message To topic Exchange = persistent
+ sendMessageOnExchange(topicExchange, topicRouting, true);
+ // and non-persistent
+ sendMessageOnExchange(topicExchange, topicRouting, false);
+
+ //Ensure all the Queues have four messages (one transient, one persistent) x 2 exchange routings
+ validateMessageOnQueues(4, true);
+ //Ensure all the topics have two messages (one transient, one persistent)
+ validateMessageOnTopics(2, true);
+
+ assertEquals("Not all queues correctly registered", 8, _virtualHost.getQueueRegistry().getQueues().size());
+
+ if (!messageStore.isPersistent())
+ {
+ _logger.warn("Unable to test Persistent capabilities of messages store(" + messageStore.getClass() + ") as it is not capable of peristence.");
+ return;
+ }
+
+ //Reload the Virtualhost to test persistence
+ _logger.info("Reloading Virtualhost");
+
+ VirtualHost original = _virtualHost;
+
+ reload(configuration);
+
+ assertTrue("Virtualhost has not been reloaded", original != _virtualHost);
+
+ validateExchanges();
+
+ //Validate Durable Queues still have the persistentn message
+ validateMessageOnQueues(2, false);
+ //Validate Durable Queues still have the persistentn message
+ validateMessageOnTopics(1, false);
+
+ //Validate Properties of Binding
+ validateBindingProperties();
+
+ //Validate Properties of Queues
+ validateQueueProperties();
+
+ //Validate Non-Durable Queues are gone.
+ assertNull("Non-Durable queue still registered:" + priorityQueueName, _virtualHost.getQueueRegistry().getQueue(priorityQueueName));
+ assertNull("Non-Durable queue still registered:" + queueName, _virtualHost.getQueueRegistry().getQueue(queueName));
+ assertNull("Non-Durable queue still registered:" + priorityTopicQueueName, _virtualHost.getQueueRegistry().getQueue(priorityTopicQueueName));
+ assertNull("Non-Durable queue still registered:" + topicQueueName, _virtualHost.getQueueRegistry().getQueue(topicQueueName));
+
+ assertEquals("Not all queues correctly registered", 4, _virtualHost.getQueueRegistry().getQueues().size());
+ }
+
+ private void validateExchanges()
+ {
+ ExchangeRegistry registry = _virtualHost.getExchangeRegistry();
+
+ assertTrue(directExchangeName + " exchange NOT reloaded after failover",
+ registry.getExchangeNames().contains(directExchangeName));
+ assertTrue(topicExchangeName + " exchange NOT reloaded after failover",
+ registry.getExchangeNames().contains(topicExchangeName));
+ assertTrue(nonDurableExchangeName + " exchange reloaded after failover",
+ !registry.getExchangeNames().contains(nonDurableExchangeName));
+
+ // There are 5 required exchanges + our 2 durable queues
+ assertEquals("Incorrect number of exchanges available", 5 + 2, registry.getExchangeNames().size());
+ }
+
+ /** Validates that the Durable queues */
+ private void validateBindingProperties()
+ {
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+
+ validateBindingProperties(queueRegistry.getQueue(durablePriorityQueueName).getExchangeBindings(), false);
+ validateBindingProperties(queueRegistry.getQueue(durablePriorityTopicQueueName).getExchangeBindings(), true);
+ validateBindingProperties(queueRegistry.getQueue(durableQueueName).getExchangeBindings(), false);
+ validateBindingProperties(queueRegistry.getQueue(durableTopicQueueName).getExchangeBindings(), true);
+ }
+
+ /**
+ * Validate that each queue is bound once.
+ *
+ * @param bindings the set of bindings to validate
+ * @param useSelectors if set validate that the binding has a JMS_SELECTOR argument
+ */
+ private void validateBindingProperties(List<ExchangeBinding> bindings, boolean useSelectors)
+ {
+ assertEquals("Each queue should only be bound once.", 1, bindings.size());
+
+ ExchangeBinding binding = bindings.get(0);
+
+ if (useSelectors)
+ {
+ assertTrue("Binding does not contain a Selector argument.",
+ binding.getArguments().containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()));
+ }
+ }
+
+ private void validateQueueProperties()
+ {
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+
+ validateQueueProperties(queueRegistry.getQueue(durablePriorityQueueName), true);
+ validateQueueProperties(queueRegistry.getQueue(durablePriorityTopicQueueName), true);
+ validateQueueProperties(queueRegistry.getQueue(durableQueueName), false);
+ validateQueueProperties(queueRegistry.getQueue(durableTopicQueueName), false);
+
+ }
+
+ private void validateQueueProperties(AMQQueue queue, boolean usePriority)
+ {
+ if (usePriority)
+ {
+ assertEquals("Queue is no longer a Priority Queue", AMQPriorityQueue.class, queue.getClass());
+ assertEquals("Priority Queue does not have set priorities", DEFAULT_PRIORTY_LEVEL, ((AMQPriorityQueue) queue).getPriorities());
+ }
+ else
+ {
+ assertEquals("Queue is no longer a Priority Queue", SimpleAMQQueue.class, queue.getClass());
+ }
+ }
+
+ /**
+ * Delete the Store Environment path
+ *
+ * @param configuration The configuration that contains the store environment path.
+ */
+ private void cleanup(Configuration configuration)
+ {
+
+ String environment = configuration.getString("store.environment-path");
+
+ if (environment != null)
+ {
+ File environmentPath = new File(environment);
+
+ if (environmentPath.exists())
+ {
+ deleteDirectory(environmentPath);
+ }
+ }
+ }
+
+ private void deleteDirectory(File path)
+ {
+ if (path.isDirectory())
+ {
+ for (File file : path.listFiles())
+ {
+ deleteDirectory(file);
+ }
+ }
+ else
+ {
+ path.delete();
+ }
+ }
+
+ private void sendMessageOnExchange(Exchange directExchange, AMQShortString routingKey, boolean deliveryMode)
+ {
+ //Set MessagePersustebce
+ BasicContentHeaderProperties properties = new BasicContentHeaderProperties();
+ properties.setDeliveryMode(deliveryMode ? Integer.valueOf(2).byteValue() : Integer.valueOf(1).byteValue());
+ FieldTable headers = properties.getHeaders();
+ headers.setString("Test", "MST");
+ properties.setHeaders(headers);
+
+ MessagePublishInfo messageInfo = new TestMessagePublishInfo(directExchange, false, false, routingKey);
+
+ IncomingMessage currentMessage = null;
+
+ try
+ {
+ currentMessage = new IncomingMessage(_virtualHost.getMessageStore().getNewMessageId(),
+ messageInfo,
+ new NonTransactionalContext(_virtualHost.getMessageStore(),
+ new StoreContext(), null, null),
+ new InternalTestProtocolSession());
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ currentMessage.setMessageStore(_virtualHost.getMessageStore());
+ currentMessage.setExchange(directExchange);
+
+ ContentHeaderBody headerBody = new ContentHeaderBody();
+ headerBody.classId = BasicConsumeBodyImpl.CLASS_ID;
+ headerBody.bodySize = 0;
+
+ headerBody.properties = properties;
+
+ try
+ {
+ currentMessage.setContentHeaderBody(headerBody);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ currentMessage.setExpiration();
+
+ try
+ {
+ currentMessage.route();
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ try
+ {
+ currentMessage.routingComplete(_virtualHost.getMessageStore(), new MessageHandleFactory());
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ // check and deliver if header says body length is zero
+ if (currentMessage.allContentReceived())
+ {
+ try
+ {
+ currentMessage.deliverToQueues();
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ private void createAllQueues()
+ {
+ //Register Durable Priority Queue
+ createQueue(durablePriorityQueueName, true, true);
+
+ //Register Durable Simple Queue
+ createQueue(durableQueueName, false, true);
+
+ //Register NON-Durable Priority Queue
+ createQueue(priorityQueueName, true, false);
+
+ //Register NON-Durable Simple Queue
+ createQueue(queueName, false, false);
+ }
+
+ private void createAllTopicQueues()
+ {
+ //Register Durable Priority Queue
+ createQueue(durablePriorityTopicQueueName, true, true);
+
+ //Register Durable Simple Queue
+ createQueue(durableTopicQueueName, false, true);
+
+ //Register NON-Durable Priority Queue
+ createQueue(priorityTopicQueueName, true, false);
+
+ //Register NON-Durable Simple Queue
+ createQueue(topicQueueName, false, false);
+ }
+
+ private Exchange createExchange(ExchangeType type, AMQShortString name, boolean durable)
+ {
+ Exchange exchange = null;
+
+ try
+ {
+ exchange = type.newInstance(_virtualHost, name, durable, 0, false);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ try
+ {
+ _virtualHost.getExchangeRegistry().registerExchange(exchange);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+ return exchange;
+ }
+
+ private void createQueue(AMQShortString queueName, boolean usePriority, boolean durable)
+ {
+
+ FieldTable queueArguments = null;
+
+ if (usePriority)
+ {
+ queueArguments = new FieldTable();
+ queueArguments.put(AMQQueueFactory.X_QPID_PRIORITIES, DEFAULT_PRIORTY_LEVEL);
+ }
+
+ AMQQueue queue = null;
+
+ //Ideally we would be able to use the QueueDeclareHandler here.
+ try
+ {
+ queue = AMQQueueFactory.createAMQQueueImpl(queueName, durable, queueOwner, false, _virtualHost,
+ queueArguments);
+
+ validateQueueProperties(queue, usePriority);
+
+ if (queue.isDurable() && !queue.isAutoDelete())
+ {
+ _virtualHost.getMessageStore().createQueue(queue, queueArguments);
+ }
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ try
+ {
+ _virtualHost.getQueueRegistry().registerQueue(queue);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ }
+
+ private void bindAllQueuesToExchange(Exchange exchange, AMQShortString routingKey)
+ {
+ FieldTable queueArguments = new FieldTable();
+ queueArguments.put(AMQQueueFactory.X_QPID_PRIORITIES, DEFAULT_PRIORTY_LEVEL);
+
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durablePriorityQueueName), false, queueArguments);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durableQueueName), false, null);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(priorityQueueName), false, queueArguments);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(queueName), false, null);
+ }
+
+ private void bindAllTopicQueuesToExchange(Exchange exchange, AMQShortString routingKey)
+ {
+ FieldTable queueArguments = new FieldTable();
+ queueArguments.put(AMQQueueFactory.X_QPID_PRIORITIES, DEFAULT_PRIORTY_LEVEL);
+
+ QueueRegistry queueRegistry = _virtualHost.getQueueRegistry();
+
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durablePriorityTopicQueueName), true, queueArguments);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durableTopicQueueName), true, null);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(priorityTopicQueueName), true, queueArguments);
+ bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(topicQueueName), true, null);
+ }
+
+
+ protected void bindQueueToExchange(Exchange exchange, AMQShortString routingKey, AMQQueue queue, boolean useSelector, FieldTable queueArguments)
+ {
+ try
+ {
+ exchange.registerQueue(queueName, queue, queueArguments);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+
+ FieldTable bindArguments = null;
+
+ if (useSelector)
+ {
+ bindArguments = new FieldTable();
+ bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), "Test = 'MST'");
+ }
+
+ try
+ {
+ queue.bind(exchange, routingKey, bindArguments);
+ }
+ catch (AMQException e)
+ {
+ fail(e.getMessage());
+ }
+ }
+
+ private void validateMessage(long messageCount, boolean allQueues)
+ {
+ validateMessageOnTopics(messageCount, allQueues);
+ validateMessageOnQueues(messageCount, allQueues);
+ }
+
+ private void validateMessageOnTopics(long messageCount, boolean allQueues)
+ {
+ validateMessageOnQueue(durablePriorityTopicQueueName, messageCount);
+ validateMessageOnQueue(durableTopicQueueName, messageCount);
+
+ if (allQueues)
+ {
+ validateMessageOnQueue(priorityTopicQueueName, messageCount);
+ validateMessageOnQueue(topicQueueName, messageCount);
+ }
+ }
+
+ private void validateMessageOnQueues(long messageCount, boolean allQueues)
+ {
+ validateMessageOnQueue(durablePriorityQueueName, messageCount);
+ validateMessageOnQueue(durableQueueName, messageCount);
+
+ if (allQueues)
+ {
+ validateMessageOnQueue(priorityQueueName, messageCount);
+ validateMessageOnQueue(queueName, messageCount);
+ }
+ }
+
+ private void validateMessageOnQueue(AMQShortString queueName, long messageCount)
+ {
+ AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueName);
+
+ assertNotNull("Queue(" + queueName + ") not correctly registered:", queue);
+
+ assertEquals("Incorrect Message count on queue:" + queueName, messageCount, queue.getMessageCount());
+ }
+
+ private class TestMessagePublishInfo implements MessagePublishInfo
+ {
+
+ Exchange _exchange;
+ boolean _immediate;
+ boolean _mandatory;
+ AMQShortString _routingKey;
+
+ TestMessagePublishInfo(Exchange exchange, boolean immediate, boolean mandatory, AMQShortString routingKey)
+ {
+ _exchange = exchange;
+ _immediate = immediate;
+ _mandatory = mandatory;
+ _routingKey = routingKey;
+ }
+
+ public AMQShortString getExchange()
+ {
+ return _exchange.getName();
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+ //no-op
+ }
+
+ public boolean isImmediate()
+ {
+ return _immediate;
+ }
+
+ public boolean isMandatory()
+ {
+ return _mandatory;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return _routingKey;
+ }
+ }
+} \ No newline at end of file
diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
new file mode 100644
index 0000000000..67eb180dbf
--- /dev/null
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java
@@ -0,0 +1,182 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.util;
+
+import junit.framework.TestCase;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.protocol.InternalTestProtocolSession;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.ConsumerTagNotUniqueException;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.exchange.ExchangeDefaults;
+
+public class InternalBrokerBaseCase extends TestCase
+{
+ protected IApplicationRegistry _registry;
+ protected MessageStore _messageStore;
+ protected AMQChannel _channel;
+ protected InternalTestProtocolSession _session;
+ protected VirtualHost _virtualHost;
+ protected StoreContext _storeContext = new StoreContext();
+ protected AMQQueue _queue;
+ protected AMQShortString QUEUE_NAME;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _registry = new TestApplicationRegistry();
+ ApplicationRegistry.initialise(_registry);
+ _virtualHost = _registry.getVirtualHostRegistry().getVirtualHost("test");
+ _messageStore = _virtualHost.getMessageStore();
+
+ QUEUE_NAME = new AMQShortString("test");
+ _queue = AMQQueueFactory.createAMQQueueImpl(QUEUE_NAME, false, new AMQShortString("testowner"),
+ false, _virtualHost, null);
+
+ _virtualHost.getQueueRegistry().registerQueue(_queue);
+
+ Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
+
+ _queue.bind(defaultExchange, QUEUE_NAME, null);
+
+ _session = new InternalTestProtocolSession();
+
+ _session.setVirtualHost(_virtualHost);
+
+ _channel = new AMQChannel(_session, 1, _messageStore);
+
+ _session.addChannel(_channel);
+ }
+
+ public void tearDown() throws Exception
+ {
+ ApplicationRegistry.removeAll();
+ super.tearDown();
+ }
+
+ protected void checkStoreContents(int messageCount)
+ {
+ assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageMetaDataMap().size());
+
+ //The above publish message is sufficiently small not to fit in the header so no Body is required.
+ //assertEquals("Message body count incorrect in the ContentBodyMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getContentBodyMap().size());
+ }
+
+ protected AMQShortString subscribe(InternalTestProtocolSession session, AMQChannel channel, AMQQueue queue)
+ {
+ try
+ {
+ return channel.subscribeToQueue(null, queue, true, null, false, true);
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ catch (ConsumerTagNotUniqueException e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ //Keep the compiler happy
+ return null;
+ }
+
+ public void publishMessages(InternalTestProtocolSession session, AMQChannel channel, int messages) throws AMQException
+ {
+ MessagePublishInfo info = new MessagePublishInfo()
+ {
+ public AMQShortString getExchange()
+ {
+ return ExchangeDefaults.DEFAULT_EXCHANGE_NAME;
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+
+ }
+
+ public boolean isImmediate()
+ {
+ return false;
+ }
+
+ public boolean isMandatory()
+ {
+ return false;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return QUEUE_NAME;
+ }
+ };
+
+ for (int count = 0; count < messages; count++)
+ {
+ channel.setPublishFrame(info, _virtualHost.getExchangeRegistry().getExchange(info.getExchange()));
+
+ //Set the body size
+ ContentHeaderBody _headerBody = new ContentHeaderBody();
+ _headerBody.bodySize = 0;
+
+ //Set Minimum properties
+ BasicContentHeaderProperties properties = new BasicContentHeaderProperties();
+
+ properties.setExpiration(0L);
+ properties.setTimestamp(System.currentTimeMillis());
+
+ //Make Message Persistent
+ properties.setDeliveryMode((byte) 2);
+
+ _headerBody.properties = properties;
+
+ channel.publishContentHeader(_headerBody);
+ }
+
+ }
+
+ public void acknowledge(AMQChannel channel, long deliveryTag)
+ {
+ try
+ {
+ channel.acknowledgeMessage(deliveryTag, false);
+ }
+ catch (AMQException e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
index 83b4665be6..15449dc613 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/util/TestApplicationRegistry.java
+++ b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java
@@ -20,29 +20,25 @@
*/
package org.apache.qpid.server.util;
+import org.apache.commons.configuration.MapConfiguration;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.management.ManagedObjectRegistry;
-import org.apache.qpid.server.plugins.PluginManager;
+import org.apache.qpid.server.management.NoopManagedObjectRegistry;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
-import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager;
import org.apache.qpid.server.security.access.ACLPlugin;
import org.apache.qpid.server.security.access.plugins.AllowAll;
+import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabaseManager;
+import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.MapConfiguration;
-import java.util.HashMap;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Properties;
+import java.util.Arrays;
public class TestApplicationRegistry extends ApplicationRegistry
{
@@ -52,17 +48,11 @@ public class TestApplicationRegistry extends ApplicationRegistry
private ExchangeFactory _exchangeFactory;
- private ManagedObjectRegistry _managedObjectRegistry;
-
- private ACLPlugin _accessManager;
-
- private PrincipalDatabaseManager _databaseManager;
-
- private AuthenticationManager _authenticationManager;
-
private MessageStore _messageStore;
+
private VirtualHost _vHost;
+
public TestApplicationRegistry()
{
super(new MapConfiguration(new HashMap()));
@@ -80,23 +70,23 @@ public class TestApplicationRegistry extends ApplicationRegistry
_authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null);
- IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
- _managedObjectRegistry = appRegistry.getManagedObjectRegistry();
- _vHost = appRegistry.getVirtualHostRegistry().getVirtualHost("test");
+ _managedObjectRegistry = new NoopManagedObjectRegistry();
+
+ _messageStore = new TestableMemoryMessageStore();
+
+ _virtualHostRegistry = new VirtualHostRegistry();
+
+ _vHost = new VirtualHost("test", _messageStore);
+
+ _virtualHostRegistry.registerVirtualHost(_vHost);
+
_queueRegistry = _vHost.getQueueRegistry();
_exchangeFactory = _vHost.getExchangeFactory();
_exchangeRegistry = _vHost.getExchangeRegistry();
- _messageStore = new TestableMemoryMessageStore();
-
_configuration.addProperty("heartbeat.delay", 10 * 60); // 10 minutes
}
- public Configuration getConfiguration()
- {
- return _configuration;
- }
-
public QueueRegistry getQueueRegistry()
{
return _queueRegistry;
@@ -112,34 +102,10 @@ public class TestApplicationRegistry extends ApplicationRegistry
return _exchangeFactory;
}
- public ManagedObjectRegistry getManagedObjectRegistry()
- {
- return _managedObjectRegistry;
- }
-
- public PrincipalDatabaseManager getDatabaseManager()
- {
- return _databaseManager;
- }
-
- public AuthenticationManager getAuthenticationManager()
- {
- return _authenticationManager;
- }
-
public Collection<String> getVirtualHostNames()
{
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public VirtualHostRegistry getVirtualHostRegistry()
- {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- public ACLPlugin getAccessManager()
- {
- return _accessManager;
+ String[] hosts = {"test"};
+ return Arrays.asList(hosts);
}
public void setAccessManager(ACLPlugin newManager)
@@ -152,10 +118,6 @@ public class TestApplicationRegistry extends ApplicationRegistry
return _messageStore;
}
- public PluginManager getPluginManager()
- {
- return null;
- }
}
diff --git a/java/build.deps b/java/build.deps
index ebbcce62a7..5ba09dc468 100644
--- a/java/build.deps
+++ b/java/build.deps
@@ -30,18 +30,20 @@ common.libs=${slf4j-api} ${backport-util-concurrent} ${mina-core} \
${mina-filter-ssl} ${commons-codec} ${commons-lang} ${commons-collections} \
${commons-configuration}
client.libs=${common.libs} ${geronimo-jms} ${junit}
+tools.libs=${client.libs}
broker.libs=${common.libs} ${commons-cli} ${commons-logging} ${log4j} \
${slf4j-log4j} ${xalan} ${felix.libs}
broker-plugins.libs=${common.libs} ${felix.libs}
-junit-toolkit.libs=${log4j} ${junit}
+junit-toolkit.libs=${log4j} ${junit} ${slf4j-api}
test.libs=${slf4j-log4j} ${junit-toolkit.libs}
systests.libs=${client.libs} ${test.libs} ${broker.libs}
perftests.libs=${systests.libs}
integrationtests.libs=${systests.libs}
client-example.libs=${client.libs}
+testkit.libs=${client.libs}
ibm-icu=lib/com.ibm.icu-3.4.4.jar
ecl-core-jface=lib/org.eclipse.jface-3.2.0.jar
@@ -73,4 +75,5 @@ management-eclipse-plugin.libs=${commons-codec} ${ibm-icu} ${ecl-core-jface} \
common.test.libs=${test.libs}
broker.test.libs=${test.libs}
client.test.libs=${broker.libs} ${test.libs}
+tools.test.libs=${client.test.libs}
management-eclipse-plugin.test.libs=${systests.libs}
diff --git a/java/build.xml b/java/build.xml
index 79dc89aa80..375fbbac94 100644
--- a/java/build.xml
+++ b/java/build.xml
@@ -22,9 +22,9 @@
<import file="common.xml"/>
- <property name="modules.core" value="junit-toolkit common broker client"/>
+ <property name="modules.core" value="junit-toolkit common broker client tools"/>
<property name="modules.examples" value="client/example"/>
- <property name="modules.tests" value="systests perftests integrationtests"/>
+ <property name="modules.tests" value="systests perftests integrationtests testkit"/>
<property name="modules.management" value="management/eclipse-plugin"/>
<property name="modules.plugin" value="broker-plugins"/>
@@ -109,7 +109,7 @@
</path>
<pathconvert property="qpid.jar.classpath" pathsep=" " dirsep="/">
<path refid="class.path"/>
- <globmapper from="${build.lib}/*" to="*"/>
+ <globmapper from="${build.lib}${file.separator}*" to="*"/>
</pathconvert>
<jar destfile="${qpid.jar}">
@@ -132,13 +132,25 @@
<target name="zip" depends="build,prepare" description="build release archive">
<zip destfile="${release.zip}">
- <zipfileset dir="${build}" prefix="${project.namever}" excludes="${release.excludes}"/>
+ <zipfileset dir="${build}" prefix="${project.namever}" filemode="755">
+ <include name="bin/*"/>
+ <exclude name="bin/*.txt"/>
+ </zipfileset>
+
+ <zipfileset dir="${build}" prefix="${project.namever}" filemode="644">
+ <include name="bin/*.txt"/>
+ </zipfileset>
+
+ <zipfileset dir="${build}" prefix="${project.namever}" excludes="${release.excludes}" filemode="644" dirmode="755">
+ <exclude name="bin/**"/>
+ <exclude name="**/*.class"/>
+ </zipfileset>
</zip>
</target>
- <target name="tar" depends="build,prepare" description="build release archive">
- <tar destfile="${release.tar}">
- <tarfileset dir="${build}" prefix="${project.namever}" excludes="${release.excludes}"/>
+ <target name="tar" depends="zip" description="build release archive">
+ <tar destfile="${release.tar}" longfile="gnu" >
+ <zipfileset src="${release.zip}"/>
</tar>
</target>
@@ -158,6 +170,7 @@
<iterate target="clean"/>
<delete dir="${build}"/>
<delete dir="${release}"/>
+ <delete dir="${tasks.classes}"/>
</target>
</project>
diff --git a/java/client/build.xml b/java/client/build.xml
index aeadfa2f0f..abeb3ec903 100644
--- a/java/client/build.xml
+++ b/java/client/build.xml
@@ -21,11 +21,10 @@
<project name="AMQ Client" default="build">
<property name="module.depends" value="common"/>
- <property name="module.test.depends" value="broker junit-toolkit"/>
<import file="../module.xml"/>
- <property name="output.dir" value="${module.precompiled}/org/apache/qpidity/filter/selector"/>
+ <property name="output.dir" value="${module.precompiled}/org/apache/qpid/filter/selector"/>
<target name="precompile">
<mkdir dir="${output.dir}"/>
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java
index 8bb27847ce..b16a7fa7c3 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java
@@ -1,8 +1,8 @@
package org.apache.qpid.example.amqpexample.direct;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
/**
* This creates a queue a queue and binds it to the
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java
index 7329792a2b..2793e567ea 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java
@@ -2,14 +2,15 @@ package org.apache.qpid.example.amqpexample.direct;
import java.nio.ByteBuffer;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
public class DirectProducer implements MessageListener
{
@@ -67,16 +68,14 @@ public class DirectProducer implements MessageListener
for (int i=0; i<10; i++)
{
- session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT,MessageAcquireMode.PRE_ACQUIRED);
- session.header(deliveryProps);
- session.data("Message " + i);
- session.endData();
+ session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT,MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProps),
+ "Message " + i);
}
- session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED);
- session.header(deliveryProps);
- session.data("That's all, folks!");
- session.endData();
+ session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProps),
+ "That's all, folks!");
// confirm completion
session.sync();
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java
index b199c3a69a..081fbf2521 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java
@@ -2,14 +2,14 @@ package org.apache.qpid.example.amqpexample.direct;
import java.nio.ByteBuffer;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-
-import org.apache.qpidity.transport.MessageCreditUnit;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+
+import org.apache.qpid.transport.MessageCreditUnit;
/**
* This listens to messages on a queue and terminates
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java
index 67f24148d8..9af5f21e66 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java
@@ -1,8 +1,8 @@
package org.apache.qpid.example.amqpexample.fanout;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
/**
* This creates a queue a queue and binds it to the
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java
index 4c647fde36..41038d3e53 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java
@@ -1,11 +1,12 @@
package org.apache.qpid.example.amqpexample.fanout;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
public class FannoutProducer
{
@@ -34,16 +35,13 @@ public class FannoutProducer
for (int i=0; i<10; i++)
{
- session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED);
- session.header(deliveryProps);
- session.data("Message " + i);
- session.endData();
+ session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProps), "Message " + i);
}
- session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED);
- session.header(deliveryProps);
- session.data("That's all, folks!");
- session.endData();
+ session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProps),
+ "That's all, folks!");
// confirm completion
session.sync();
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java
index 1feb5cfe23..7942ce5ca3 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java
@@ -2,16 +2,16 @@ package org.apache.qpid.example.amqpexample.fanout;
import java.nio.ByteBuffer;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
-import org.apache.qpidity.transport.MessageCreditUnit;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageCreditUnit;
/**
* This listens to messages on a queue and terminates
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java
index f26e5418b4..2e4edfbe6f 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java
@@ -2,14 +2,14 @@ package org.apache.qpid.example.amqpexample.pubsub;
import java.nio.ByteBuffer;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-import org.apache.qpidity.transport.MessageCreditUnit;
-import org.apache.qpidity.transport.Option;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.transport.MessageCreditUnit;
+import org.apache.qpid.transport.Option;
public class TopicListener implements MessageListener
@@ -55,7 +55,7 @@ public class TopicListener implements MessageListener
Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED,
Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE,
new MessagePartListenerAdapter(this),
- null, Option.NO_OPTION);
+ null, Option.NONE);
// issue credits
// XXX: need to be able to set to null
session.messageFlow(queueName, MessageCreditUnit.BYTE, Session.MESSAGE_FLOW_MAX_BYTES);
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java
index c960643504..caec886642 100755
--- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java
@@ -1,11 +1,12 @@
package org.apache.qpid.example.amqpexample.pubsub;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
public class TopicPublisher
{
@@ -18,20 +19,17 @@ public class TopicPublisher
deliveryProps.setRoutingKey(routing_key);
for (int i=0; i<5; i++) {
- session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED);
- session.header(deliveryProps);
- session.data("Message " + i);
- session.endData();
+ session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProps), "Message " + i);
}
}
public void noMoreMessages(Session session)
{
- session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED);
- session.header(new DeliveryProperties().setRoutingKey("control"));
- session.data("That's all, folks!");
- session.endData();
+ session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey("control")),
+ "That's all, folks!");
}
public static void main(String[] args)
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify
index afcd30af88..0541e490b6 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify
@@ -2,12 +2,13 @@
# The JMS producer doesn't create qeueues so utilising the c++ declare_queues
cpp=$CPP/direct
-direct_consumer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
+direct_consumer_java()
+{
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
}
direct_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
}
clients $cpp/declare_queues direct_producer_java direct_consumer_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_cpp_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_cpp_java
index 85c8a12903..d581c4c1aa 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_cpp_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_cpp_java
@@ -2,7 +2,7 @@
cpp=$CPP/direct
direct_consumer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
}
clients $cpp/declare_queues $cpp/direct_producer direct_consumer_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_cpp b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_cpp
index 8cea77025e..573cac6986 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_cpp
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_cpp
@@ -2,7 +2,7 @@
cpp=$CPP/direct
direct_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
}
clients $cpp/declare_queues direct_producer_java $cpp/listener
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_python b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_python
index 5fedcb10e5..61c033e969 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_python
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_java_python
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/direct
+py=$PYTHON_EXAMPLES/direct
direct_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Producer
}
clients $py/declare_queues.py direct_producer_java $py/direct_consumer.py
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_python_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_python_java
index 7914665baf..4182331f3f 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_python_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/direct/verify_python_java
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/direct
+py=$PYTHON_EXAMPLES/direct
direct_consumer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.direct.Consumer
}
clients $py/declare_queues.py $py/direct_producer.py direct_consumer_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify
index 69528a0cf9..2edc1ced02 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify
@@ -3,11 +3,11 @@
cpp=$CPP/fanout
fanout_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
}
fanout_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
}
background "can receive messages" fanout_listener_java fanoutQueue1
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_cpp_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_cpp_java
index 3e0d7534bc..de057ea3b1 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_cpp_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_cpp_java
@@ -3,7 +3,7 @@
cpp=$CPP/fanout
fanout_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
}
background "can receive messages" fanout_listener_java fanoutQueue1
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_cpp b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_cpp
index c1e1585ac3..dab6114572 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_cpp
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_cpp
@@ -3,7 +3,7 @@
cpp=$CPP/fanout
fanout_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
}
background "Listening" $cpp/listener
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_python b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_python
index b57cb4af38..1641d88354 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_python
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_java_python
@@ -1,9 +1,9 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
# The JMS producer doesn't create qeueues so utilising the c++ declare_queues
-py=$PYTHON/fanout
+py=$PYTHON_EXAMPLES/fanout
fanout_producer_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Producer
}
background "Subscribed" $py/fanout_consumer.py
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_python_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_python_java
index e10d077dfb..0f05663985 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_python_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/fanout/verify_python_java
@@ -1,9 +1,9 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
# The JMS producer doesn't create qeueues so utilising the c++ declare_queues
-py=$PYTHON/fanout
+py=$PYTHON_EXAMPLES/fanout
fanout_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.fanout.Listener $1
}
background "can receive messages" fanout_listener_java fanoutQueue1
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify
index 3e2a1b9b04..cceb565dfc 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify
@@ -2,11 +2,11 @@
cpp=$CPP/pub-sub
topic_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
}
topic_publisher_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
}
background "can receive messages" topic_listener_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_cpp_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_cpp_java
index f189290fda..9276b3e21b 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_cpp_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_cpp_java
@@ -2,7 +2,7 @@
cpp=$CPP/pub-sub
topic_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
}
background "can receive messages" topic_listener_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_cpp b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_cpp
index 87743681f4..af22b3b82c 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_cpp
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_cpp
@@ -2,7 +2,7 @@
cpp=$CPP/pub-sub
topic_publisher_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
}
background "Listening" $cpp/topic_listener
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_python b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_python
index a8daf6ba30..3758e0f014 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_python
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_java_python
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/pubsub
+py=$PYTHON_EXAMPLES/pubsub
topic_publisher_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Publisher
}
background "Queues created" $py/topic_subscriber.py
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_python_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_python_java
index fc8f526145..c2b516f376 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_python_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/pubsub/verify_python_java
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/pubsub
+py=$PYTHON_EXAMPLES/pubsub
topic_listener_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.pubsub.Listener
}
background "can receive messages" topic_listener_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify
index b3b0735d53..daf84c8ff9 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify
@@ -2,11 +2,11 @@
cpp=$CPP/pub-sub
client_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
}
server_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
}
background "can receive messages" server_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_cpp_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_cpp_java
index 4551b9ab0c..6ef1b3b7e3 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_cpp_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_cpp_java
@@ -1,8 +1,9 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
cpp=$CPP/request-response
-client_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
+client_java()
+{
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
}
background "Waiting" $cpp/server
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_cpp b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_cpp
index 27510dc3f7..2513eb691b 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_cpp
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_cpp
@@ -2,7 +2,7 @@
cpp=$CPP/request-response
server_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
}
background "can receive messages" server_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_python b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_python
index 01bec87cab..0760952527 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_python
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_java_python
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/request-response
+py=$PYTHON_EXAMPLES/request-response
server_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Server
}
background "can receive messages" server_java
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_python_java b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_python_java
index 92a33f4a1e..6ea526e914 100644
--- a/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_python_java
+++ b/java/client/example/src/main/java/org/apache/qpid/example/jmsexample/requestResponse/verify_python_java
@@ -1,8 +1,8 @@
# See https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid/bin/verify
-py=$PYTHON/request-response
+py=$PYTHON_EXAMPLES/request-response
client_java(){
-java -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
+java -Dlog4j.configuration=file://"$JAVA"/log4j.xml -cp "$CLASSPATH" org.apache.qpid.example.jmsexample.requestResponse.Client
}
background "Request server running" $py/server.py
diff --git a/java/client/pom.xml b/java/client/pom.xml
index bcce3e1d3b..2ad41d96cd 100644
--- a/java/client/pom.xml
+++ b/java/client/pom.xml
@@ -112,7 +112,7 @@
<configuration>
<sourceDirectory>${basedir}/src/main/grammar</sourceDirectory>
<outputDirectory>${basedir}/target/generated-sources</outputDirectory>
- <packageName>org.apache.qpidity.filter.selector</packageName>
+ <packageName>org.apache.qpid.filter.selector</packageName>
</configuration>
<goals>
<goal>javacc</goal>
@@ -237,16 +237,16 @@
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<excludePackageNames>
- org.apache.qpid.*:org.apache.qpidity.njms:org.apache.qpidity.njms.*:org.apache.qpidity.nclient.impl
+ org.apache.qpid.*:org.apache.qpid.njms:org.apache.qpid.njms.*:org.apache.qpid.nclient.impl
</excludePackageNames>
<groups>
<group>
<title>API</title>
- <packages>org.apache.qpidity.nclient</packages>
+ <packages>org.apache.qpid.nclient</packages>
</group>
<group>
<title>Utility Package</title>
- <packages>org.apache.qpidity.nclient.util</packages>
+ <packages>org.apache.qpid.nclient.util</packages>
</group>
</groups>
</configuration>
diff --git a/java/client/src/main/grammar/SelectorParser.jj b/java/client/src/main/grammar/SelectorParser.jj
index a72da526ae..b45cf1a487 100644
--- a/java/client/src/main/grammar/SelectorParser.jj
+++ b/java/client/src/main/grammar/SelectorParser.jj
@@ -61,20 +61,20 @@ PARSER_BEGIN(SelectorParser)
*
*/
-package org.apache.qpidity.filter.selector;
+package org.apache.qpid.filter.selector;
import java.io.StringReader;
import java.util.ArrayList;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.filter.ArithmeticExpression;
-import org.apache.qpidity.filter.BooleanExpression;
-import org.apache.qpidity.filter.ComparisonExpression;
-import org.apache.qpidity.filter.ConstantExpression;
-import org.apache.qpidity.filter.Expression;
-import org.apache.qpidity.filter.LogicExpression;
-import org.apache.qpidity.filter.PropertyExpression;
-import org.apache.qpidity.filter.UnaryExpression;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.filter.ArithmeticExpression;
+import org.apache.qpid.filter.BooleanExpression;
+import org.apache.qpid.filter.ComparisonExpression;
+import org.apache.qpid.filter.ConstantExpression;
+import org.apache.qpid.filter.Expression;
+import org.apache.qpid.filter.LogicExpression;
+import org.apache.qpid.filter.PropertyExpression;
+import org.apache.qpid.filter.UnaryExpression;
/**
* JMS Selector Parser generated by JavaCC
diff --git a/java/client/src/main/java/client.log4j b/java/client/src/main/java/client.log4j
index a5531bb874..19cc946118 100644
--- a/java/client/src/main/java/client.log4j
+++ b/java/client/src/main/java/client.log4j
@@ -21,15 +21,10 @@ log4j.rootLogger=${root.logging.level}
#log4j.logger.org.apache.qpid=${amqj.logging.level}, console
#log4j.additivity.org.apache.qpid=false
-#log4j.logger.org.apache.qpidity.transport=TRACE, console
log4j.logger.org.apache.qpid=ERROR, console
log4j.additivity.org.apache.qpid=false
-log4j.logger.org.apache.qpidity=ERROR, console
-log4j.additivity.org.apache.qpidity=false
-
-#log4j.logger.org.apache.qpidity.transport=DEBUG, console
#log4j.logger.org.apache.qpid.client.message.AbstractBytesTypedMessage=DEBUG, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index a504fb2c27..27294562e5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -36,7 +36,6 @@ import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.FailoverPolicy;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.url.URLSyntaxException;
-import org.apache.qpidity.transport.TransportConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,7 +57,9 @@ import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.net.ConnectException;
+import java.net.UnknownHostException;
import java.nio.channels.UnresolvedAddressException;
import java.text.MessageFormat;
import java.util.*;
@@ -78,7 +79,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public AMQSession get(int channelId)
{
- if((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
+ if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
return _fastAccessSessions[channelId];
}
@@ -91,7 +92,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public AMQSession put(int channelId, AMQSession session)
{
AMQSession oldVal;
- if((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
+ if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
oldVal = _fastAccessSessions[channelId];
_fastAccessSessions[channelId] = session;
@@ -100,11 +101,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
oldVal = _slowAccessSessions.put(channelId, session);
}
- if((oldVal != null) && (session == null))
+ if ((oldVal != null) && (session == null))
{
_size--;
}
- else if((oldVal == null) && (session != null))
+ else if ((oldVal == null) && (session != null))
{
_size++;
}
@@ -113,13 +114,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
-
public AMQSession remove(int channelId)
{
AMQSession session;
- if((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
+ if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
- session = _fastAccessSessions[channelId];
+ session = _fastAccessSessions[channelId];
_fastAccessSessions[channelId] = null;
}
else
@@ -127,7 +127,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
session = _slowAccessSessions.remove(channelId);
}
- if(session != null)
+ if (session != null)
{
_size--;
}
@@ -139,9 +139,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
ArrayList<AMQSession> values = new ArrayList<AMQSession>(size());
- for(int i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
{
- if(_fastAccessSessions[i] != null)
+ if (_fastAccessSessions[i] != null)
{
values.add(_fastAccessSessions[i]);
}
@@ -160,14 +160,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_size = 0;
_slowAccessSessions.clear();
- for(int i = 0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
_fastAccessSessions[i] = null;
}
}
}
-
private static final Logger _logger = LoggerFactory.getLogger(AMQConnection.class);
protected AtomicInteger _idFactory = new AtomicInteger(0);
@@ -209,7 +208,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/** The virtual path to connect to on the AMQ server */
private String _virtualHost;
-
protected ExceptionListener _exceptionListener;
@@ -232,11 +230,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
protected boolean _connected;
/*
- * The last error code that occured on the connection. Used to return the correct exception to the client
- */
- protected AMQException _lastAMQException = null;
-
- /*
* The connection meta data
*/
private QpidConnectionMetaData _connectionMetaData;
@@ -255,7 +248,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private ProtocolVersion _protocolVersion = ProtocolVersion.v0_9; // FIXME TGM, shouldn't need this
protected AMQConnectionDelegate _delegate;
-
+
// this connection maximum number of prefetched messages
private long _maxPrefetch;
@@ -337,20 +330,20 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/**
* @todo Some horrible stuff going on here with setting exceptions to be non-null to detect if an exception
- * was thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon.
+ * was thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon.
*/
public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException
{
// set this connection maxPrefetch
if (connectionURL.getOption(ConnectionURL.AMQ_MAXPREFETCH) != null)
{
- _maxPrefetch = Long.parseLong( connectionURL.getOption(ConnectionURL.AMQ_MAXPREFETCH));
+ _maxPrefetch = Long.parseLong(connectionURL.getOption(ConnectionURL.AMQ_MAXPREFETCH));
}
else
{
// use the defaul value set for all connections
_maxPrefetch = Long.valueOf(System.getProperties().getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME,
- ClientProperties.MAX_PREFETCH_DEFAULT));
+ ClientProperties.MAX_PREFETCH_DEFAULT));
}
if (connectionURL.getOption(ConnectionURL.AMQ_SYNC_PERSISTENCE) != null)
@@ -367,37 +360,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
BrokerDetails brokerDetails = _failoverPolicy.getNextBrokerDetails();
if (brokerDetails.getTransport().equals(BrokerDetails.VM))
{
- _delegate = new AMQConnectionDelegate_0_8(this);
+ _delegate = new AMQConnectionDelegate_8_0(this);
}
else
{
- // We always assume that the broker supports the lates AMQ protocol verions
- // thie is currently 0.10
- // TODO: use this code once we have switch to 0.10
- // getDelegate();
_delegate = new AMQConnectionDelegate_0_10(this);
}
- final ArrayList<JMSException> exceptions = new ArrayList<JMSException>();
-
- class Listener implements ExceptionListener
- {
- public void onException(JMSException e)
- {
- exceptions.add(e);
- }
- }
-
- try
- {
- setExceptionListener(new Listener());
- }
- catch (JMSException e)
- {
- // Shouldn't happen
- throw new AMQException(null, null, e);
- }
-
if (_logger.isInfoEnabled())
{
_logger.info("Connection:" + connectionURL);
@@ -437,47 +406,40 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_temporaryTopicExchangeName = connectionURL.getTemporaryTopicExchangeName();
}
-
- _protocolHandler = new AMQProtocolHandler(this);
+ _protocolHandler = new AMQProtocolHandler(this);
// We are not currently connected
_connected = false;
- Exception lastException = new Exception();
- lastException.initCause(new ConnectException());
-
- // TMG FIXME this seems... wrong...
boolean retryAllowed = true;
- while (!_connected && retryAllowed )
+ Exception connectionException = null;
+ while (!_connected && retryAllowed)
{
+ ProtocolVersion pe = null;
try
{
- makeBrokerConnection(brokerDetails);
- lastException = null;
- _connected = true;
+ pe = makeBrokerConnection(brokerDetails);
}
- catch (AMQProtocolException pe)
+ catch (Exception e)
{
if (_logger.isInfoEnabled())
{
- _logger.info(pe.getMessage());
- _logger.info("Trying broker supported protocol version: " +
- TransportConstants.getVersionMajor() + "." +
- TransportConstants.getVersionMinor());
+ _logger.info("Unable to connect to broker at " +
+ _failoverPolicy.getCurrentBrokerDetails(),
+ e);
}
- // we need to check whether we have a delegate for the supported protocol
- getDelegate();
+ connectionException = e;
}
- catch (Exception e)
- {
- lastException = e;
- if (_logger.isInfoEnabled())
- {
- _logger.info("Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails(),
- e.getCause());
- }
- retryAllowed = _failoverPolicy.failoverAllowed();
+ if (pe != null)
+ {
+ // reset the delegate to the version returned by the
+ // broker
+ initDelegate(pe);
+ }
+ else if (!_connected)
+ {
+ retryAllowed = _failoverPolicy.failoverAllowed();
brokerDetails = _failoverPolicy.getNextBrokerDetails();
}
}
@@ -490,39 +452,17 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if (!_connected)
{
String message = null;
- try
- {
- Thread.sleep(150);
- }
- catch (InterruptedException e)
- {
- // Eat it, we've hopefully got all the exceptions if this happened
- }
- if (exceptions.size() > 0)
- {
- JMSException e = exceptions.get(0);
- int code = -1;
- try
- {
- code = new Integer(e.getErrorCode()).intValue();
- }
- catch (NumberFormatException nfe)
- {
- // Ignore this, we have some error codes and messages swapped around
- }
- throw new AMQConnectionFailureException(AMQConstant.getConstant(code),
- e.getMessage(), e);
- }
- else if (lastException != null)
+ if (connectionException != null)
{
- if (lastException.getCause() != null)
+ if (connectionException.getCause() != null)
{
- message = lastException.getCause().getMessage();
+ message = connectionException.getCause().getMessage();
+ connectionException.getCause().printStackTrace();
}
else
{
- message = lastException.getMessage();
+ message = connectionException.getMessage();
}
}
@@ -534,27 +474,23 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
else // can only be "" if getMessage() returned it therfore lastException != null
{
- message = "Unable to Connect:" + lastException.getClass();
+ message = "Unable to Connect:" + connectionException.getClass();
}
}
- AMQException e = new AMQConnectionFailureException(message, null);
-
- if (lastException != null)
+ for (Throwable th = connectionException; th != null; th = th.getCause())
{
- if (lastException instanceof UnresolvedAddressException)
+ if (th instanceof UnresolvedAddressException ||
+ th instanceof UnknownHostException)
{
- e = new AMQUnresolvedAddressException(message, _failoverPolicy.getCurrentBrokerDetails().toString(),
- null);
+ throw new AMQUnresolvedAddressException
+ (message,
+ _failoverPolicy.getCurrentBrokerDetails().toString(),
+ connectionException);
}
-
- if (e.getCause() != null)
- {
- e.initCause(lastException);
- }
}
- throw e;
+ throw new AMQConnectionFailureException(message, connectionException);
}
_connectionMetaData = new QpidConnectionMetaData(this);
@@ -572,23 +508,41 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return ((cause instanceof ConnectException) || (cause instanceof UnresolvedAddressException));
}
- private void getDelegate() throws AMQProtocolException
+ private void initDelegate(ProtocolVersion pe) throws AMQProtocolException
{
try
{
- Class c = Class.forName("org.apache.qpid.client.AMQConnectionDelegate_" +
- TransportConstants.getVersionMajor() + "_" +
- TransportConstants.getVersionMinor());
- Class partypes[] = new Class[1];
+ Class c = Class.forName(String.format
+ ("org.apache.qpid.client.AMQConnectionDelegate_%s_%s",
+ pe.getMajorVersion(), pe.getMinorVersion()));
+ Class partypes[] = new Class[1];
partypes[0] = AMQConnection.class;
_delegate = (AMQConnectionDelegate) c.getConstructor(partypes).newInstance(this);
}
- catch (Exception e)
+ catch (ClassNotFoundException e)
+ {
+ throw new AMQProtocolException
+ (AMQConstant.UNSUPPORTED_CLIENT_PROTOCOL_ERROR,
+ String.format("Protocol: %s.%s is rquired by the broker but is not " +
+ "currently supported by this client library implementation",
+ pe.getMajorVersion(), pe.getMinorVersion()),
+ e);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new RuntimeException("unable to locate constructor for delegate", e);
+ }
+ catch (InstantiationException e)
+ {
+ throw new RuntimeException("error instantiating delegate", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException("error accessing delegate", e);
+ }
+ catch (InvocationTargetException e)
{
- throw new AMQProtocolException(AMQConstant.UNSUPPORTED_CLIENT_PROTOCOL_ERROR,
- "Protocol: " + TransportConstants.getVersionMajor() + "."
- + TransportConstants.getVersionMinor() + " is rquired by the broker but is not " +
- "currently supported by this client library implementation", e);
+ throw new RuntimeException("error invoking delegate", e);
}
}
@@ -669,9 +623,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return false;
}
- public void makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException
+ public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException
{
- _delegate.makeBrokerConnection(brokerDetail);
+ return _delegate.makeBrokerConnection(brokerDetail);
}
/**
@@ -879,7 +833,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
-
}
}
@@ -904,14 +857,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
- public void close() throws JMSException
+ public void close() throws JMSException
{
close(DEFAULT_TIMEOUT);
}
public void close(long timeout) throws JMSException
{
- close(new ArrayList<AMQSession>(_sessions.values()),timeout);
+ close(new ArrayList<AMQSession>(_sessions.values()), timeout);
}
public void close(List<AMQSession> sessions, long timeout) throws JMSException
@@ -924,12 +877,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private void doClose(List<AMQSession> sessions, long timeout) throws JMSException
{
- synchronized(_sessionCreationLock)
+ synchronized (_sessionCreationLock)
{
- if(!sessions.isEmpty())
+ if (!sessions.isEmpty())
{
AMQSession session = sessions.remove(0);
- synchronized(session.getMessageDeliveryLock())
+ synchronized (session.getMessageDeliveryLock())
{
doClose(sessions, timeout);
}
@@ -1132,7 +1085,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
return _sessions;
}
-
+
public String getUsername()
{
return _username;
@@ -1309,6 +1262,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if (cause instanceof IOException)
{
closer = !_closed.getAndSet(true);
+
+ _protocolHandler.getProtocolSession().notifyError(je);
}
if (_exceptionListener != null)
@@ -1351,7 +1306,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
if (cause instanceof AMQException)
{
- return ((AMQException)cause).isHardError();
+ return ((AMQException) cause).isHardError();
}
return true;
@@ -1367,24 +1322,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_sessions.remove(channelId);
}
- /**
- * For all sessions, and for all consumers in those sessions, resubscribe. This is called during failover handling.
- * The caller must hold the failover mutex before calling this method.
- */
- public void resubscribeSesssions() throws JMSException, AMQException, FailoverException
- {
- ArrayList sessions = new ArrayList(_sessions.values());
- _logger.info(MessageFormat.format("Resubscribing sessions = {0} sessions.size={1}", sessions, sessions.size())); // FIXME: removeKey?
- for (Iterator it = sessions.iterator(); it.hasNext();)
- {
- AMQSession s = (AMQSession) it.next();
- // _protocolHandler.addSessionByChannel(s.getChannelId(), s);
- reopenChannel(s.getChannelId(), s.getDefaultPrefetchHigh(), s.getDefaultPrefetchLow(), s.getTransacted());
- s.resubscribe();
- s.setFlowControl(true);
- }
- }
-
public String toString()
{
StringBuffer buf = new StringBuffer("AMQConnection:\n");
@@ -1495,7 +1432,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
*/
public long getMaxPrefetch()
{
- return _maxPrefetch;
+ return _maxPrefetch;
}
/**
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
index 07bd7ea0ae..7f36ec6e99 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java
@@ -27,12 +27,13 @@ import javax.jms.XASession;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.Session;
public interface AMQConnectionDelegate
{
- public void makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException;
+ public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException;
public Session createSession(final boolean transacted, final int acknowledgeMode,
final int prefetchHigh, final int prefetchLow) throws JMSException;
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
index 61c06df7a5..a2df2f3cf2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java
@@ -9,13 +9,14 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.AMQProtocolException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.Session;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.ClosedListener;
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.ProtocolException;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.ClosedListener;
+import org.apache.qpid.ErrorCode;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.transport.ProtocolVersionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,7 +35,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Closed
/**
* The QpidConeection instance that is mapped with thie JMS connection.
*/
- org.apache.qpidity.nclient.Connection _qpidConnection;
+ org.apache.qpid.nclient.Connection _qpidConnection;
//--- constructor
public AMQConnectionDelegate_0_10(AMQConnection conn)
@@ -101,7 +102,7 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Closed
* @throws IOException
* @throws AMQException
*/
- public void makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException
+ public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException
{
_qpidConnection = Client.createConnection();
try
@@ -115,15 +116,18 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Closed
_qpidConnection.connect(brokerDetail.getHost(), brokerDetail.getPort(), _conn.getVirtualHost(),
_conn.getUsername(), _conn.getPassword());
_qpidConnection.setClosedListener(this);
+ _conn._connected = true;
}
- catch(ProtocolException pe)
+ catch(ProtocolVersionException pe)
{
- throw new AMQProtocolException(null, pe.getMessage(), pe);
+ return new ProtocolVersion(pe.getMajor(), pe.getMinor());
}
catch (QpidException e)
{
throw new AMQException(AMQConstant.CHANNEL_ERROR, "cannot connect to broker", e);
}
+
+ return null;
}
/**
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_9.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_9.java
new file mode 100755
index 0000000000..d95e2e3dff
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_9.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client;
+
+
+public class AMQConnectionDelegate_0_9 extends AMQConnectionDelegate_8_0
+{
+
+ public AMQConnectionDelegate_0_9(AMQConnection conn)
+ {
+ super(conn);
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
index 637cff5b7e..2ec8737d16 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
@@ -25,7 +25,9 @@ import java.net.ConnectException;
import java.nio.channels.UnresolvedAddressException;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.Iterator;
+import java.util.Set;
import javax.jms.JMSException;
import javax.jms.XASession;
@@ -35,21 +37,24 @@ import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.failover.FailoverRetrySupport;
import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.client.state.StateWaiter;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.BasicQosBody;
import org.apache.qpid.framing.BasicQosOkBody;
import org.apache.qpid.framing.ChannelOpenBody;
import org.apache.qpid.framing.ChannelOpenOkBody;
+import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.framing.TxSelectBody;
import org.apache.qpid.framing.TxSelectOkBody;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.jms.ChannelLimitReachedException;
+import org.apache.qpid.transport.network.io.IoTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class AMQConnectionDelegate_0_8 implements AMQConnectionDelegate
+public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate
{
- private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionDelegate_0_8.class);
+ private static final Logger _logger = LoggerFactory.getLogger(AMQConnectionDelegate_8_0.class);
private AMQConnection _conn;
@@ -59,7 +64,7 @@ public class AMQConnectionDelegate_0_8 implements AMQConnectionDelegate
}
- public AMQConnectionDelegate_0_8(AMQConnection conn)
+ public AMQConnectionDelegate_8_0(AMQConnection conn)
{
_conn = conn;
}
@@ -76,24 +81,36 @@ public class AMQConnectionDelegate_0_8 implements AMQConnectionDelegate
return ((cause instanceof ConnectException) || (cause instanceof UnresolvedAddressException));
}
- public void makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, AMQException
+ public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws AMQException, IOException
{
- try
+ final Set<AMQState> openOrClosedStates =
+ EnumSet.of(AMQState.CONNECTION_OPEN, AMQState.CONNECTION_CLOSED);
+
+
+ StateWaiter waiter = _conn._protocolHandler.createWaiter(openOrClosedStates);
+
+ // TODO: use system property thingy for this
+ if (System.getProperty("UseTransportIo", "false").equals("false"))
{
TransportConnection.getInstance(brokerDetail).connect(_conn._protocolHandler, brokerDetail);
- // this blocks until the connection has been set up or when an error
- // has prevented the connection being set up
- _conn._protocolHandler.attainState(AMQState.CONNECTION_OPEN);
- _conn._failoverPolicy.attainedConnection();
-
- // Again this should be changed to a suitable notify
- _conn._connected = true;
+ }
+ else
+ {
+ _conn.getProtocolHandler().createIoTransportSession(brokerDetail);
}
- catch (AMQException e)
+
+ // this blocks until the connection has been set up or when an error
+ // has prevented the connection being set up
+
+ AMQState state = waiter.await();
+
+ if(state == AMQState.CONNECTION_OPEN)
{
- _conn._lastAMQException = e;
- throw e;
+ _conn._failoverPolicy.attainedConnection();
+ _conn._connected = true;
}
+
+ return null;
}
public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode, final int prefetch)
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
index fd8063e99b..01a915f2cc 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java
@@ -38,7 +38,6 @@ import javax.naming.spi.ObjectFactory;
import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.URLSyntaxException;
-import org.apache.qpidity.transport.TransportConstants;
public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory,
@@ -294,14 +293,23 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
public Connection createConnection(String userName, String password) throws JMSException
{
+ return createConnection(userName, password, null);
+ }
+
+ public Connection createConnection(String userName, String password, String id) throws JMSException
+ {
try
{
if (_connectionDetails != null)
{
_connectionDetails.setUsername(userName);
_connectionDetails.setPassword(password);
-
- if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
+
+ if (id != null && !id.equals(""))
+ {
+ _connectionDetails.setClientName(id);
+ }
+ else if (_connectionDetails.getClientName() == null || _connectionDetails.getClientName().equals(""))
{
_connectionDetails.setClientName(getUniqueClientID());
}
@@ -309,7 +317,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
}
else
{
- return new AMQConnection(_host, _port, userName, password, getUniqueClientID(), _virtualPath);
+ return new AMQConnection(_host, _port, userName, password, (id != null ? id : getUniqueClientID()), _virtualPath);
}
}
catch (Exception e)
@@ -434,23 +442,15 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF
*/
public XAConnection createXAConnection() throws JMSException
{
- if (TransportConstants.getVersionMajor() == 0 &&
- TransportConstants.getVersionMinor() == 8)
+ try
{
- throw new UnsupportedOperationException("This protocol version does not support XA operations");
+ return new XAConnectionImpl(_connectionDetails, _sslConfig);
}
- else
+ catch (Exception e)
{
- try
- {
- return new XAConnectionImpl(_connectionDetails, _sslConfig);
- }
- catch (Exception e)
- {
- JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
- jmse.setLinkedException(e);
- throw jmse;
- }
+ JMSException jmse = new JMSException("Error creating connection: " + e.getMessage());
+ jmse.setLinkedException(e);
+ throw jmse;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
index 0ac73d7460..21b63c1fdb 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
@@ -289,7 +289,7 @@ public class AMQConnectionURL implements ConnectionURL
public static void main(String[] args) throws URLSyntaxException
{
String url2 =
- "amqp://ritchiem:bob@temp?brokerlist='tcp://localhost:5672;jcp://fancyserver:3000/',failover='roundrobin'";
+ "amqp://ritchiem:bob@temp/testHost?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
// "amqp://user:pass@clientid/virtualhost?brokerlist='tcp://host:1?option1=\'value\',option2=\'value\';vm://:3?option1=\'value\'',failover='method?option1=\'value\',option2='value''";
ConnectionURL connectionurl2 = new AMQConnectionURL(url2);
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
index 52080112c9..6c78b754bb 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
@@ -65,9 +65,9 @@ public abstract class AMQDestination implements Destination, Referenceable
private static final int IS_EXCLUSIVE_MASK = 0x2;
private static final int IS_AUTODELETE_MASK = 0x4;
- public static final Integer QUEUE_TYPE = Integer.valueOf(1);
- public static final Integer TOPIC_TYPE = Integer.valueOf(2);
- public static final Integer UNKNOWN_TYPE = Integer.valueOf(3);
+ public static final int QUEUE_TYPE = 1;
+ public static final int TOPIC_TYPE = 2;
+ public static final int UNKNOWN_TYPE = 3;
protected AMQDestination(String url) throws URISyntaxException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index 3b51fb8db0..5203a27f42 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -63,63 +63,54 @@ import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQInvalidArgumentException;
import org.apache.qpid.AMQInvalidRoutingKeyException;
-import org.apache.qpid.AMQUndeliveredException;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverNoopSupport;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.failover.FailoverRetrySupport;
-import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.JMSBytesMessage;
-import org.apache.qpid.client.message.JMSMapMessage;
-import org.apache.qpid.client.message.JMSObjectMessage;
-import org.apache.qpid.client.message.JMSStreamMessage;
-import org.apache.qpid.client.message.JMSTextMessage;
-import org.apache.qpid.client.message.MessageFactoryRegistry;
-import org.apache.qpid.client.message.ReturnMessage;
-import org.apache.qpid.client.message.UnprocessedMessage;
+import org.apache.qpid.client.message.*;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.util.FlowControllingBlockingQueue;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.url.AMQBindingURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- *
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td>
* </table>
*
* @todo Different FailoverSupport implementation are needed on the same method call, in different situations. For
- * example, when failing-over and reestablishing the bindings, the bind cannot be interrupted by a second
- * fail-over, if it fails with an exception, the fail-over process should also fail. When binding outside of
- * the fail-over process, the retry handler could be used to automatically retry the operation once the connection
- * has been reestablished. All fail-over protected operations should be placed in private methods, with
- * FailoverSupport passed in by the caller to provide the correct support for the calling context. Sometimes the
- * fail-over process sets a nowait flag and uses an async method call instead.
- *
+ * example, when failing-over and reestablishing the bindings, the bind cannot be interrupted by a second
+ * fail-over, if it fails with an exception, the fail-over process should also fail. When binding outside of
+ * the fail-over process, the retry handler could be used to automatically retry the operation once the connection
+ * has been reestablished. All fail-over protected operations should be placed in private methods, with
+ * FailoverSupport passed in by the caller to provide the correct support for the calling context. Sometimes the
+ * fail-over process sets a nowait flag and uses an async method call instead.
* @todo Two new objects created on every failover supported method call. Consider more efficient ways of doing this,
- * after looking at worse bottlenecks first.
+ * after looking at worse bottlenecks first.
*/
-public abstract class AMQSession extends Closeable implements Session, QueueSession, TopicSession
+public abstract class AMQSession<C extends BasicMessageConsumer, P extends BasicMessageProducer> extends Closeable implements Session, QueueSession, TopicSession
{
- public static final class IdToConsumerMap
+
+
+ public static final class IdToConsumerMap<C extends BasicMessageConsumer>
{
private final BasicMessageConsumer[] _fastAccessConsumers = new BasicMessageConsumer[16];
- private final ConcurrentHashMap<Integer, BasicMessageConsumer> _slowAccessConsumers = new ConcurrentHashMap<Integer, BasicMessageConsumer>();
-
+ private final ConcurrentHashMap<Integer, C> _slowAccessConsumers = new ConcurrentHashMap<Integer, C>();
- public BasicMessageConsumer get(int id)
+ public C get(int id)
{
- if((id & 0xFFFFFFF0) == 0)
+ if ((id & 0xFFFFFFF0) == 0)
{
- return _fastAccessConsumers[id];
+ return (C) _fastAccessConsumers[id];
}
else
{
@@ -127,12 +118,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- public BasicMessageConsumer put(int id, BasicMessageConsumer consumer)
+ public C put(int id, C consumer)
{
- BasicMessageConsumer oldVal;
- if((id & 0xFFFFFFF0) == 0)
+ C oldVal;
+ if ((id & 0xFFFFFFF0) == 0)
{
- oldVal = _fastAccessConsumers[id];
+ oldVal = (C) _fastAccessConsumers[id];
_fastAccessConsumers[id] = consumer;
}
else
@@ -144,13 +135,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
-
- public BasicMessageConsumer remove(int id)
+ public C remove(int id)
{
- BasicMessageConsumer consumer;
- if((id & 0xFFFFFFF0) == 0)
+ C consumer;
+ if ((id & 0xFFFFFFF0) == 0)
{
- consumer = _fastAccessConsumers[id];
+ consumer = (C) _fastAccessConsumers[id];
_fastAccessConsumers[id] = null;
}
else
@@ -162,15 +152,15 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
- public Collection<BasicMessageConsumer> values()
+ public Collection<C> values()
{
- ArrayList<BasicMessageConsumer> values = new ArrayList<BasicMessageConsumer>();
+ ArrayList<C> values = new ArrayList<C>();
- for(int i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
{
- if(_fastAccessConsumers[i] != null)
+ if (_fastAccessConsumers[i] != null)
{
- values.add(_fastAccessConsumers[i]);
+ values.add((C) _fastAccessConsumers[i]);
}
}
values.addAll(_slowAccessConsumers.values());
@@ -178,11 +168,10 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
return values;
}
-
public void clear()
{
_slowAccessConsumers.clear();
- for(int i = 0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
_fastAccessConsumers[i] = null;
}
@@ -192,8 +181,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
/** Used for debugging. */
private static final Logger _logger = LoggerFactory.getLogger(AMQSession.class);
- /** Used for debugging in the dispatcher. */
- private static final Logger _dispatcherLogger = LoggerFactory.getLogger(Dispatcher.class);
/** The default maximum number of prefetched message at which to suspend the channel. */
public static final int DEFAULT_PREFETCH_HIGH_MARK = 5000;
@@ -243,7 +230,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
/** Holds this session unique identifier, used to distinguish it from other sessions. */
protected int _channelId;
- /** @todo This does not appear to be set? */
private int _ticket;
/** Holds the high mark for prefetched message, at which the session is suspended. */
@@ -270,8 +256,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* Holds a mapping from message consumers to their identifying names, so that their subscriptions may be looked
* up in the {@link #_subscriptions} map.
*/
- protected final ConcurrentHashMap<BasicMessageConsumer, String> _reverseSubscriptionMap =
- new ConcurrentHashMap<BasicMessageConsumer, String>();
+ protected final ConcurrentHashMap<C, String> _reverseSubscriptionMap =
+ new ConcurrentHashMap<C, String>();
/**
* Used to hold incoming messages.
@@ -280,19 +266,13 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*/
protected final FlowControllingBlockingQueue _queue;
- /**
- * Holds the highest received delivery tag.
- */
+ /** Holds the highest received delivery tag. */
private final AtomicLong _highestDeliveryTag = new AtomicLong(-1);
- /**
- * All the not yet acknowledged message tags
- */
+ /** All the not yet acknowledged message tags */
protected ConcurrentLinkedQueue<Long> _unacknowledgedMessageTags = new ConcurrentLinkedQueue<Long>();
- /**
- * All the delivered message tags
- */
+ /** All the delivered message tags */
protected ConcurrentLinkedQueue<Long> _deliveredMessageTags = new ConcurrentLinkedQueue<Long>();
/** Holds the dispatcher thread for this session. */
@@ -314,16 +294,16 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* Maps from identifying tags to message consumers, in order to pass dispatch incoming messages to the right
* consumer.
*/
- protected final IdToConsumerMap _consumers = new IdToConsumerMap();
-
- //Map<AMQShortString, BasicMessageConsumer> _consumers =
- //new ConcurrentHashMap<AMQShortString, BasicMessageConsumer>();
+ protected final IdToConsumerMap<C> _consumers = new IdToConsumerMap<C>();
+
+ //Map<AMQShortString, BasicMessageConsumer> _consumers =
+ //new ConcurrentHashMap<AMQShortString, BasicMessageConsumer>();
/**
* Contains a list of consumers which have been removed but which might still have
* messages to acknowledge, eg in client ack or transacted modes
*/
- private CopyOnWriteArrayList<BasicMessageConsumer> _removedConsumers = new CopyOnWriteArrayList<BasicMessageConsumer>();
+ private CopyOnWriteArrayList<C> _removedConsumers = new CopyOnWriteArrayList<C>();
/** Provides a count of consumers on destinations, in order to be able to know if a destination has consumers. */
private ConcurrentHashMap<Destination, AtomicInteger> _destinationConsumerCount =
@@ -377,10 +357,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
/** Session state : used to detect if commit is a) required b) allowed , i.e. does the tx span failover. */
private boolean _dirty;
- /** Has failover occured on this session */
- private boolean _failedOver;
-
-
+ /** Has failover occured on this session with outstanding actions to commit? */
+ private boolean _failedOverDirty;
private static final class FlowControlIndicator
{
@@ -388,7 +366,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public synchronized void setFlowControl(boolean flowControl)
{
- _flowControl= flowControl;
+ _flowControl = flowControl;
notify();
}
@@ -412,7 +390,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param defaultPrefetchHighMark The maximum number of messages to prefetched before suspending the session.
* @param defaultPrefetchLowMark The number of prefetched messages at which to resume the session.
*/
- AMQSession(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode,
+ protected AMQSession(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode,
MessageFactoryRegistry messageFactoryRegistry, int defaultPrefetchHighMark, int defaultPrefetchLowMark)
{
@@ -445,21 +423,25 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
new FlowControllingBlockingQueue(_defaultPrefetchHighMark, _defaultPrefetchLowMark,
new FlowControllingBlockingQueue.ThresholdListener()
{
+ private final AtomicBoolean _suspendState = new AtomicBoolean();
+
public void aboveThreshold(int currentValue)
{
- _logger.debug(
- "Above threshold(" + _defaultPrefetchHighMark
- + ") so suspending channel. Current value is " + currentValue);
- new Thread(new SuspenderRunner(true)).start();
+ _logger.debug(
+ "Above threshold(" + _defaultPrefetchHighMark
+ + ") so suspending channel. Current value is " + currentValue);
+ _suspendState.set(true);
+ new Thread(new SuspenderRunner(_suspendState)).start();
}
public void underThreshold(int currentValue)
{
- _logger.debug(
- "Below threshold(" + _defaultPrefetchLowMark
- + ") so unsuspending channel. Current value is " + currentValue);
- new Thread(new SuspenderRunner(false)).start();
+ _logger.debug(
+ "Below threshold(" + _defaultPrefetchLowMark
+ + ") so unsuspending channel. Current value is " + currentValue);
+ _suspendState.set(false);
+ new Thread(new SuspenderRunner(_suspendState)).start();
}
});
@@ -499,10 +481,30 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
close(-1);
}
+ public void checkNotClosed() throws JMSException
+ {
+ try
+ {
+ super.checkNotClosed();
+ }
+ catch (IllegalStateException ise)
+ {
+ // if the Connection has closed then we should throw any exception that has occured that we were not waiting for
+ AMQStateManager manager = _connection.getProtocolHandler().getStateManager();
+
+ if (manager.getCurrentState().equals(AMQState.CONNECTION_CLOSED) && manager.getLastException() != null)
+ {
+ ise.setLinkedException(manager.getLastException());
+ }
+
+ throw ise;
+ }
+ }
+
public BytesMessage createBytesMessage() throws JMSException
{
checkNotClosed();
- return new JMSBytesMessage();
+ return new JMSBytesMessage(getMessageDelegateFactory());
}
/**
@@ -515,7 +517,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
if (isClosed())
{
throw new IllegalStateException("Session is already closed");
- }
+ }
else if (hasFailedOver())
{
throw new IllegalStateException("has failed over");
@@ -560,39 +562,35 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param exchangeName The exchange to bind the queue on.
*
* @throws AMQException If the queue cannot be bound for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
- *
* @todo Document the additional arguments that may be passed in the field table. Are these for headers exchanges?
*/
public void bindQueue(final AMQShortString queueName, final AMQShortString routingKey, final FieldTable arguments,
- final AMQShortString exchangeName,final AMQDestination destination) throws AMQException
+ final AMQShortString exchangeName, final AMQDestination destination) throws AMQException
{
/*new FailoverRetrySupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>()*/
new FailoverNoopSupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>()
{
public Object execute() throws AMQException, FailoverException
{
- sendQueueBind(queueName,routingKey,arguments,exchangeName,destination);
+ sendQueueBind(queueName, routingKey, arguments, exchangeName, destination);
return null;
}
}, _connection).execute();
}
-
- public void addBindingKey(BasicMessageConsumer consumer, AMQDestination amqd, String routingKey) throws AMQException
+ public void addBindingKey(C consumer, AMQDestination amqd, String routingKey) throws AMQException
{
- if( consumer.getQueuename() != null)
+ if (consumer.getQueuename() != null)
{
- bindQueue(consumer.getQueuename(), new AMQShortString(routingKey), new FieldTable(), amqd.getExchangeName(),amqd);
+ bindQueue(consumer.getQueuename(), new AMQShortString(routingKey), new FieldTable(), amqd.getExchangeName(), amqd);
}
}
public abstract void sendQueueBind(final AMQShortString queueName, final AMQShortString routingKey, final FieldTable arguments,
- final AMQShortString exchangeName,AMQDestination destination) throws AMQException, FailoverException;
+ final AMQShortString exchangeName, AMQDestination destination) throws AMQException, FailoverException;
/**
-
* Closes the session.
*
* <p/>Note that this operation succeeds automatically if a fail-over interupts the sycnronous request to close
@@ -602,14 +600,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param timeout The timeout in milliseconds to wait for the session close acknoledgement from the broker.
*
* @throws JMSException If the JMS provider fails to close the session due to some internal error.
- *
* @todo Be aware of possible changes to parameter order as versions change.
- *
* @todo Not certain about the logic of ignoring the failover exception, because the channel won't be
- * re-opened. May need to examine this more carefully.
- *
+ * re-opened. May need to examine this more carefully.
* @todo Note that taking the failover mutex doesn't prevent this operation being interrupted by a failover,
- * because the failover process sends the failover event before acquiring the mutex itself.
+ * because the failover process sends the failover event before acquiring the mutex itself.
*/
public void close(long timeout) throws JMSException
{
@@ -617,13 +612,13 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
_logger.info("Closing session: " + this); // + ":"
- // + Arrays.asList(stackTrace).subList(3, stackTrace.length - 1));
+ // + Arrays.asList(stackTrace).subList(3, stackTrace.length - 1));
}
// Ensure we only try and close an open session.
if (!_closed.getAndSet(true))
{
- synchronized (_connection.getFailoverMutex())
+ synchronized (getFailoverMutex())
{
// We must close down all producers and consumers in an orderly fashion. This is the only method
// that can be called from a different thread of control from the one controlling the session.
@@ -634,7 +629,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
try
{
- sendClose(timeout);
+ sendClose(timeout);
}
catch (AMQException e)
{
@@ -685,7 +680,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
if (!_closed.getAndSet(true))
{
- synchronized (_connection.getFailoverMutex())
+ synchronized (getFailoverMutex())
{
synchronized (_messageDeliveryLock)
{
@@ -701,7 +696,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
amqe = new AMQException("Closing session forcibly", e);
}
-
_connection.deregisterSession(_channelId);
closeProducersAndConsumers(amqe);
}
@@ -719,12 +713,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @throws JMSException If the JMS provider fails to commit the transaction due to some internal error. This does
* not mean that the commit is known to have failed, merely that it is not known whether it
* failed or not.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
public void commit() throws JMSException
{
- checkTransacted();
+ checkTransacted();
try
{
@@ -743,6 +736,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
// Commits outstanding messages and acknowledgments
sendCommit();
+ markClean();
}
catch (AMQException e)
{
@@ -756,11 +750,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public abstract void sendCommit() throws AMQException, FailoverException;
- public void confirmConsumerCancelled(AMQShortString consumerTag)
+
+ public void confirmConsumerCancelled(int consumerTag)
{
// Remove the consumer from the map
- BasicMessageConsumer consumer = _consumers.get(consumerTag.toIntValue());
+ C consumer = _consumers.get(consumerTag);
if (consumer != null)
{
if (!consumer.isNoConsume()) // Normal Consumer
@@ -788,10 +783,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
// consumer.markClosed();
-
-
if (consumer.isAutoClose())
- {
+ {
// There is a small window where the message is between the two queues in the dispatcher.
if (consumer.isClosed())
{
@@ -802,6 +795,10 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
deregisterConsumer(consumer);
}
+ else
+ {
+ _queue.add(new CloseConsumerMessage(consumer));
+ }
}
}
}
@@ -847,7 +844,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
false, false);
}
- public MessageConsumer createExclusiveConsumer(Destination destination) throws JMSException
+ public C createExclusiveConsumer(Destination destination) throws JMSException
{
checkValidDestination(destination);
@@ -855,7 +852,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
false, false);
}
-
public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException
{
checkValidDestination(destination);
@@ -873,7 +869,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
messageSelector, null, false, false);
}
-
public MessageConsumer createExclusiveConsumer(Destination destination, String messageSelector, boolean noLocal)
throws JMSException
{
@@ -883,7 +878,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
messageSelector, null, false, false);
}
-
public MessageConsumer createConsumer(Destination destination, int prefetch, boolean noLocal, boolean exclusive,
String selector) throws JMSException
{
@@ -920,7 +914,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public abstract TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException;
public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal)
- throws JMSException
+ throws JMSException
{
checkNotClosed();
checkValidTopic(topic);
@@ -929,8 +923,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
_subscriptions.get(name).close();
}
AMQTopic dest = AMQTopic.createDurableTopic((AMQTopic) topic, name, _connection);
- BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal);
- TopicSubscriberAdaptor subscriber = new TopicSubscriberAdaptor(dest, consumer);
+ C consumer = (C) createConsumer(dest, messageSelector, noLocal);
+ TopicSubscriberAdaptor<C> subscriber = new TopicSubscriberAdaptor(dest, consumer);
_subscriptions.put(name, subscriber);
_reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name);
@@ -940,7 +934,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public MapMessage createMapMessage() throws JMSException
{
checkNotClosed();
- return new JMSMapMessage();
+ return new JMSMapMessage(getMessageDelegateFactory());
}
public javax.jms.Message createMessage() throws JMSException
@@ -951,7 +945,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public ObjectMessage createObjectMessage() throws JMSException
{
checkNotClosed();
- return (ObjectMessage) new JMSObjectMessage();
+ return (ObjectMessage) new JMSObjectMessage(getMessageDelegateFactory());
}
public ObjectMessage createObjectMessage(Serializable object) throws JMSException
@@ -962,23 +956,23 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
return msg;
}
- public BasicMessageProducer createProducer(Destination destination) throws JMSException
+ public P createProducer(Destination destination) throws JMSException
{
return createProducerImpl(destination, DEFAULT_MANDATORY, DEFAULT_IMMEDIATE);
}
- public BasicMessageProducer createProducer(Destination destination, boolean immediate) throws JMSException
+ public P createProducer(Destination destination, boolean immediate) throws JMSException
{
return createProducerImpl(destination, DEFAULT_MANDATORY, immediate);
}
- public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate)
+ public P createProducer(Destination destination, boolean mandatory, boolean immediate)
throws JMSException
{
return createProducerImpl(destination, mandatory, immediate);
}
- public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate,
+ public P createProducer(Destination destination, boolean mandatory, boolean immediate,
boolean waitUntilSent) throws JMSException
{
return createProducerImpl(destination, mandatory, immediate, waitUntilSent);
@@ -988,7 +982,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
checkNotClosed();
- return new TopicPublisherAdapter((BasicMessageProducer) createProducer(topic,false,false), topic);
+ return new TopicPublisherAdapter((P) createProducer(topic, false, false), topic);
}
public Queue createQueue(String queueName) throws JMSException
@@ -1025,24 +1019,44 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param exclusive Flag to indicate that the queue is exclusive to this client.
*
* @throws AMQException If the queue cannot be declared for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
public void createQueue(final AMQShortString name, final boolean autoDelete, final boolean durable,
final boolean exclusive) throws AMQException
{
+ createQueue(name, autoDelete, durable, exclusive, null);
+ }
+
+ /**
+ * Declares the named queue.
+ *
+ * <p/>Note that this operation automatically retries in the event of fail-over.
+ *
+ * @param name The name of the queue to declare.
+ * @param autoDelete
+ * @param durable Flag to indicate that the queue is durable.
+ * @param exclusive Flag to indicate that the queue is exclusive to this client.
+ * @param arguments Arguments used to set special properties of the queue
+ *
+ * @throws AMQException If the queue cannot be declared for any reason.
+ * @todo Be aware of possible changes to parameter order as versions change.
+ */
+ public void createQueue(final AMQShortString name, final boolean autoDelete, final boolean durable,
+ final boolean exclusive, final Map<String, Object> arguments) throws AMQException
+ {
new FailoverRetrySupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>()
{
public Object execute() throws AMQException, FailoverException
{
- sendCreateQueue(name, autoDelete, durable, exclusive);
+ sendCreateQueue(name, autoDelete, durable, exclusive, arguments);
return null;
}
}, _connection).execute();
}
public abstract void sendCreateQueue(AMQShortString name, final boolean autoDelete, final boolean durable,
- final boolean exclusive)throws AMQException, FailoverException;
+ final boolean exclusive, final Map<String, Object> arguments) throws AMQException, FailoverException;
+
/**
* Creates a QueueReceiver
*
@@ -1056,7 +1070,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
checkValidDestination(destination);
AMQQueue dest = (AMQQueue) destination;
- BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(destination);
+ C consumer = (C) createConsumer(destination);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1075,7 +1089,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
checkValidDestination(destination);
AMQQueue dest = (AMQQueue) destination;
- BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(destination, messageSelector);
+ C consumer = (C) createConsumer(destination, messageSelector);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1093,7 +1107,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
checkNotClosed();
AMQQueue dest = (AMQQueue) queue;
- BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest);
+ C consumer = (C) createConsumer(dest);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1112,7 +1126,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
checkNotClosed();
AMQQueue dest = (AMQQueue) queue;
- BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector);
+ C consumer = (C) createConsumer(dest, messageSelector);
return new QueueReceiverAdaptor(dest, consumer);
}
@@ -1127,11 +1141,18 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public StreamMessage createStreamMessage() throws JMSException
{
- synchronized (_connection.getFailoverMutex())
+ // This method needs to be improved. Throwables only arrive here from the mina : exceptionRecived
+ // calls through connection.closeAllSessions which is also called by the public connection.close()
+ // with a null cause
+ // When we are closing the Session due to a protocol session error we simply create a new AMQException
+ // with the correct error code and text this is cleary WRONG as the instanceof check below will fail.
+ // We need to determin here if the connection should be
+
+ synchronized (getFailoverMutex())
{
checkNotClosed();
- return new JMSStreamMessage();
+ return new JMSStreamMessage(getMessageDelegateFactory());
}
}
@@ -1150,10 +1171,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
AMQTopic dest = checkValidTopic(topic);
// AMQTopic dest = new AMQTopic(topic.getTopicName());
- return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createExclusiveConsumer(dest));
+ return new TopicSubscriberAdaptor(dest, (C) createExclusiveConsumer(dest));
}
-
/**
* Creates a non-durable subscriber with a message selector
*
@@ -1171,7 +1191,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
AMQTopic dest = checkValidTopic(topic);
// AMQTopic dest = new AMQTopic(topic.getTopicName());
- return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createExclusiveConsumer(dest, messageSelector, noLocal));
+ return new TopicSubscriberAdaptor(dest, (C) createExclusiveConsumer(dest, messageSelector, noLocal));
}
public abstract TemporaryQueue createTemporaryQueue() throws JMSException;
@@ -1185,14 +1205,19 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public TextMessage createTextMessage() throws JMSException
{
- synchronized (_connection.getFailoverMutex())
+ synchronized (getFailoverMutex())
{
checkNotClosed();
- return new JMSTextMessage();
+ return new JMSTextMessage(getMessageDelegateFactory());
}
}
+ protected Object getFailoverMutex()
+ {
+ return _connection.getFailoverMutex();
+ }
+
public TextMessage createTextMessage(String text) throws JMSException
{
@@ -1340,17 +1365,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
_logger.debug("Message[" + message.toString() + "] received in session");
}
-
- if (message instanceof ReturnMessage)
- {
- // Return of the bounced message.
- returnBouncedMessage((ReturnMessage)message);
- }
- else
- {
- _highestDeliveryTag.set(message.getDeliveryTag());
- _queue.add(message);
- }
+ _highestDeliveryTag.set(message.getDeliveryTag());
+ _queue.add(message);
}
public void declareAndBind(AMQDestination amqd)
@@ -1360,7 +1376,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
AMQProtocolHandler protocolHandler = getProtocolHandler();
declareExchange(amqd, protocolHandler, false);
AMQShortString queueName = declareQueue(amqd, protocolHandler, false);
- bindQueue(queueName, amqd.getRoutingKey(), new FieldTable(), amqd.getExchangeName(),amqd);
+ bindQueue(queueName, amqd.getRoutingKey(), new FieldTable(), amqd.getExchangeName(), amqd);
}
/**
@@ -1375,7 +1391,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* <li>Stop message delivery.</li>
* <li>Mark all messages that might have been delivered but not acknowledged as "redelivered".
* <li>Restart the delivery sequence including all unacknowledged messages that had been previously delivered.
- * Redelivered messages do not have to be delivered in exactly their original delivery order.</li>
+ * Redelivered messages do not have to be delivered in exactly their original delivery order.</li>
* </ul>
*
* <p/>If the recover operation is interrupted by a fail-over, between asking that the broker begin recovery and
@@ -1429,7 +1445,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- abstract void sendRecover() throws AMQException, FailoverException;
+ protected abstract void sendRecover() throws AMQException, FailoverException;
public void rejectMessage(UnprocessedMessage message, boolean requeue)
{
@@ -1465,7 +1481,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @throws JMSException If the JMS provider fails to rollback the transaction due to some internal error. This does
* not mean that the rollback is known to have failed, merely that it is not known whether it
* failed or not.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
public void rollback() throws JMSException
@@ -1507,8 +1522,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public abstract void releaseForRollback();
- public abstract void sendRollback() throws AMQException, FailoverException ;
-
+ public abstract void sendRollback() throws AMQException, FailoverException;
public void run()
{
@@ -1576,7 +1590,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
deleteQueue(AMQTopic.getDurableTopicQueueName(name, _connection));
}
- else
+ else // Queue Browser
{
if (isQueueBound(getDefaultTopicExchangeName(), AMQTopic.getDurableTopicQueueName(name, _connection)))
@@ -1591,7 +1605,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- protected MessageConsumer createConsumerImpl(final Destination destination, final int prefetchHigh,
+ protected C createConsumerImpl(final Destination destination, final int prefetchHigh,
final int prefetchLow, final boolean noLocal, final boolean exclusive, String selector, final FieldTable rawSelector,
final boolean noConsume, final boolean autoClose) throws JMSException
{
@@ -1615,10 +1629,10 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
messageSelector = selector;
}
- return new FailoverRetrySupport<MessageConsumer, JMSException>(
- new FailoverProtectedOperation<MessageConsumer, JMSException>()
+ return new FailoverRetrySupport<C, JMSException>(
+ new FailoverProtectedOperation<C, JMSException>()
{
- public MessageConsumer execute() throws JMSException, FailoverException
+ public C execute() throws JMSException, FailoverException
{
checkNotClosed();
@@ -1630,13 +1644,19 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
final FieldTable ft = FieldTableFactory.newFieldTable();
// if (rawSelector != null)
// ft.put("headers", rawSelector.getDataAsBytes());
- if (rawSelector != null)
+ // rawSelector is used by HeadersExchange and is not a JMS Selector
+ if (rawSelector != null)
{
ft.addAll(rawSelector);
}
+
+ if (messageSelector != null)
+ {
+ ft.put(new AMQShortString("x-filter-jms-selector"), messageSelector);
+ }
- BasicMessageConsumer consumer = createMessageConsumer(amqd, prefetchHigh,prefetchLow,
- noLocal,exclusive, messageSelector, ft, noConsume, autoClose);
+ C consumer = createMessageConsumer(amqd, prefetchHigh, prefetchLow,
+ noLocal, exclusive, messageSelector, ft, noConsume, autoClose);
if (_messageListener != null)
{
@@ -1679,9 +1699,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}, _connection).execute();
}
- public abstract BasicMessageConsumer createMessageConsumer(final AMQDestination destination, final int prefetchHigh,
- final int prefetchLow, final boolean noLocal, final boolean exclusive, String selector, final FieldTable rawSelector,
- final boolean noConsume, final boolean autoClose) throws JMSException;
+ public abstract C createMessageConsumer(final AMQDestination destination, final int prefetchHigh,
+ final int prefetchLow, final boolean noLocal, final boolean exclusive, String selector, final FieldTable arguments,
+ final boolean noConsume, final boolean autoClose) throws JMSException;
/**
* Called by the MessageConsumer when closing, to deregister the consumer from the map from consumerTag to consumer
@@ -1689,9 +1709,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*
* @param consumer the consum
*/
- void deregisterConsumer(BasicMessageConsumer consumer)
+ void deregisterConsumer(C consumer)
{
- if (_consumers.remove(consumer.getConsumerTag().toIntValue()) != null)
+ if (_consumers.remove(consumer.getConsumerTag()) != null)
{
String subscriptionName = _reverseSubscriptionMap.remove(consumer);
if (subscriptionName != null)
@@ -1744,12 +1764,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @return <tt>true</tt> if the queue is bound to the exchange and routing key, <tt>false</tt> if not.
*
* @throws JMSException If the query fails for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
public abstract boolean isQueueBound(final AMQShortString exchangeName, final AMQShortString queueName, final AMQShortString routingKey)
throws JMSException;
-
+
public abstract boolean isQueueBound(final AMQDestination destination) throws JMSException;
/**
@@ -1771,7 +1790,10 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*/
void resubscribe() throws AMQException
{
- _failedOver = true;
+ if (_dirty)
+ {
+ _failedOverDirty = true;
+ }
resubscribeProducers();
resubscribeConsumers();
}
@@ -1790,10 +1812,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* Starts the session, which ensures that it is not suspended and that its event dispatcher is running.
*
* @throws AMQException If the session cannot be started for any reason.
- *
* @todo This should be controlled by _stopped as it pairs with the stop method fixme or check the
- * FlowControlledBlockingQueue _queue to see if we have flow controlled. will result in sending Flow messages
- * for each subsequent call to flow.. only need to do this if we have called stop.
+ * FlowControlledBlockingQueue _queue to see if we have flow controlled. will result in sending Flow messages
+ * for each subsequent call to flow.. only need to do this if we have called stop.
*/
void start() throws AMQException
{
@@ -1978,12 +1999,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
// we need to clone the list of consumers since the close() method updates the _consumers collection
// which would result in a concurrent modification exception
- final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList<BasicMessageConsumer>(_consumers.values());
+ final ArrayList<C> clonedConsumers = new ArrayList<C>(_consumers.values());
- final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator();
+ final Iterator<C> it = clonedConsumers.iterator();
while (it.hasNext())
{
- final BasicMessageConsumer con = it.next();
+ final C con = it.next();
if (error != null)
{
con.notifyError(error);
@@ -1994,7 +2015,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
// at this point the _consumers map will be empty
- if (_dispatcher != null)
+ if (_dispatcher != null)
{
_dispatcher.close();
_dispatcher = null;
@@ -2014,7 +2035,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
final Iterator it = clonedProducers.iterator();
while (it.hasNext())
{
- final BasicMessageProducer prod = (BasicMessageProducer) it.next();
+ final P prod = (P) it.next();
prod.close();
}
// at this point the _producers map is empty
@@ -2062,20 +2083,18 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*
* @param queueName
*/
- private void consumeFromQueue(BasicMessageConsumer consumer, AMQShortString queueName,
+ private void consumeFromQueue(C consumer, AMQShortString queueName,
AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector) throws AMQException, FailoverException
{
int tagId = _nextTag++;
- // need to generate a consumer tag on the client so we can exploit the nowait flag
- AMQShortString tag = new AMQShortString(Integer.toString(tagId));
- consumer.setConsumerTag(tag);
+ consumer.setConsumerTag(tagId);
// we must register the consumer in the map before we actually start listening
_consumers.put(tagId, consumer);
try
{
- sendConsume(consumer, queueName, protocolHandler, nowait, messageSelector, tag);
+ sendConsume(consumer, queueName, protocolHandler, nowait, messageSelector, tagId);
}
catch (AMQException e)
{
@@ -2085,27 +2104,27 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- public abstract void sendConsume(BasicMessageConsumer consumer, AMQShortString queueName,
- AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector,AMQShortString tag) throws AMQException, FailoverException;
+ public abstract void sendConsume(C consumer, AMQShortString queueName,
+ AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector, int tag) throws AMQException, FailoverException;
- private BasicMessageProducer createProducerImpl(Destination destination, boolean mandatory, boolean immediate)
+ private P createProducerImpl(Destination destination, boolean mandatory, boolean immediate)
throws JMSException
{
return createProducerImpl(destination, mandatory, immediate, false);
}
- private BasicMessageProducer createProducerImpl(final Destination destination, final boolean mandatory,
+ private P createProducerImpl(final Destination destination, final boolean mandatory,
final boolean immediate, final boolean waitUntilSent) throws JMSException
{
- return new FailoverRetrySupport<BasicMessageProducer, JMSException>(
- new FailoverProtectedOperation<BasicMessageProducer, JMSException>()
+ return new FailoverRetrySupport<P, JMSException>(
+ new FailoverProtectedOperation<P, JMSException>()
{
- public BasicMessageProducer execute() throws JMSException, FailoverException
+ public P execute() throws JMSException, FailoverException
{
checkNotClosed();
long producerId = getNextProducerId();
- BasicMessageProducer producer = createMessageProducer(destination, mandatory,
- immediate, waitUntilSent, producerId);
+ P producer = createMessageProducer(destination, mandatory,
+ immediate, waitUntilSent, producerId);
registerProducer(producerId, producer);
return producer;
@@ -2113,21 +2132,20 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}, _connection).execute();
}
- public abstract BasicMessageProducer createMessageProducer(final Destination destination, final boolean mandatory,
- final boolean immediate, final boolean waitUntilSent, long producerId);
+ public abstract P createMessageProducer(final Destination destination, final boolean mandatory,
+ final boolean immediate, final boolean waitUntilSent, long producerId);
private void declareExchange(AMQDestination amqd, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException
{
declareExchange(amqd.getExchangeName(), amqd.getExchangeClass(), protocolHandler, nowait);
}
-
/**
* Returns the number of messages currently queued for the given destination.
*
* <p/>Note that this operation automatically retries in the event of fail-over.
*
- * @param amqd The destination to be checked
+ * @param amqd The destination to be checked
*
* @return the number of queued messages.
*
@@ -2147,7 +2165,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
- abstract Long requestQueueDepth(AMQDestination amqd) throws AMQException, FailoverException;
+ protected abstract Long requestQueueDepth(AMQDestination amqd) throws AMQException, FailoverException;
/**
* Declares the named exchange and type of exchange.
@@ -2160,7 +2178,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param nowait
*
* @throws AMQException If the exchange cannot be declared for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
private void declareExchange(final AMQShortString name, final AMQShortString type,
@@ -2177,8 +2194,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
public abstract void sendExchangeDeclare(final AMQShortString name, final AMQShortString type, final AMQProtocolHandler protocolHandler,
- final boolean nowait) throws AMQException, FailoverException;
-
+ final boolean nowait) throws AMQException, FailoverException;
/**
* Declares a queue for a JMS destination.
@@ -2196,9 +2212,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* the client.
*
* @throws AMQException If the queue cannot be declared for any reason.
- *
* @todo Verify the destiation is valid or throw an exception.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler,
@@ -2224,7 +2238,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}, _connection).execute();
}
- public abstract void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler)throws AMQException, FailoverException;
+ public abstract void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler) throws AMQException, FailoverException;
/**
* Undeclares the specified queue.
@@ -2234,7 +2248,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* @param queueName The name of the queue to delete.
*
* @throws JMSException If the queue could not be deleted for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
protected void deleteQueue(final AMQShortString queueName) throws JMSException
@@ -2256,7 +2269,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- public abstract void sendQueueDelete(final AMQShortString queueName) throws AMQException, FailoverException;
+ public abstract void sendQueueDelete(final AMQShortString queueName) throws AMQException, FailoverException;
private long getNextProducerId()
{
@@ -2292,12 +2305,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
// we need to clone the list of consumers since the close() method updates the _consumers collection
// which would result in a concurrent modification exception
- final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList<BasicMessageConsumer>(_consumers.values());
+ final ArrayList<C> clonedConsumers = new ArrayList<C>(_consumers.values());
- final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator();
+ final Iterator<C> it = clonedConsumers.iterator();
while (it.hasNext())
{
- final BasicMessageConsumer con = it.next();
+ final C con = it.next();
con.markClosed();
}
// at this point the _consumers map will be empty
@@ -2332,7 +2345,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*
* @throws AMQException
*/
- private void registerConsumer(BasicMessageConsumer consumer, boolean nowait) throws AMQException // , FailoverException
+ private void registerConsumer(C consumer, boolean nowait) throws AMQException // , FailoverException
{
AMQDestination amqd = consumer.getDestination();
@@ -2345,8 +2358,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
// store the consumer queue name
consumer.setQueuename(queueName);
- // bindQueue(amqd, queueName, protocolHandler, consumer.getRawSelectorFieldTable());
- bindQueue(queueName, amqd.getRoutingKey(), consumer.getRawSelectorFieldTable(), amqd.getExchangeName(),amqd);
+ bindQueue(queueName, amqd.getRoutingKey(), consumer.getArguments(), amqd.getExchangeName(), amqd);
// If IMMEDIATE_PREFETCH is not required then suspsend the channel to delay prefetch
if (!_immediatePrefetch)
@@ -2397,15 +2409,16 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
private void rejectAllMessages(boolean requeue)
{
- rejectMessagesForConsumerTag(null, requeue);
+ rejectMessagesForConsumerTag(0, requeue, true);
}
/**
* @param consumerTag The consumerTag to prune from queue or all if null
* @param requeue Should the removed messages be requeued (or discarded. Possibly to DLQ)
+ * @param rejectAllConsumers
*/
- private void rejectMessagesForConsumerTag(AMQShortString consumerTag, boolean requeue)
+ private void rejectMessagesForConsumerTag(int consumerTag, boolean requeue, boolean rejectAllConsumers)
{
Iterator messages = _queue.iterator();
if (_logger.isInfoEnabled())
@@ -2426,12 +2439,12 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
UnprocessedMessage message = (UnprocessedMessage) messages.next();
- if ((consumerTag == null) || message.getConsumerTag().equals(consumerTag.toString()))
+ if (rejectAllConsumers || (message.getConsumerTag() == consumerTag))
{
if (_logger.isDebugEnabled())
{
_logger.debug("Removing message(" + System.identityHashCode(message) + ") from _queue DT:"
- + message.getDeliveryTag());
+ + message.getDeliveryTag());
}
messages.remove();
@@ -2448,12 +2461,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
private void resubscribeConsumers() throws AMQException
{
- ArrayList consumers = new ArrayList(_consumers.values());
+ ArrayList<C> consumers = new ArrayList<C>(_consumers.values());
_consumers.clear();
- for (Iterator it = consumers.iterator(); it.hasNext();)
- {
- BasicMessageConsumer consumer = (BasicMessageConsumer) it.next();
+ for (C consumer : consumers)
+ {
consumer.failedOver();
registerConsumer(consumer, true);
}
@@ -2465,53 +2477,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
_logger.info(MessageFormat.format("Resubscribing producers = {0} producers.size={1}", producers, producers.size())); // FIXME: removeKey
for (Iterator it = producers.iterator(); it.hasNext();)
{
- BasicMessageProducer producer = (BasicMessageProducer) it.next();
+ P producer = (P) it.next();
producer.resubscribe();
}
}
- private void returnBouncedMessage(final ReturnMessage msg)
- {
- _connection.performConnectionTask(new Runnable()
- {
- public void run()
- {
- try
- {
- // Bounced message is processed here, away from the mina thread
- AbstractJMSMessage bouncedMessage =
- _messageFactoryRegistry.createMessage(0, false, msg.getExchange(),
- msg.getRoutingKey(), msg.getContentHeader(), msg.getBodies());
- AMQConstant errorCode = AMQConstant.getConstant(msg.getReplyCode());
- AMQShortString reason = msg.getReplyText();
- _logger.debug("Message returned with error code " + errorCode + " (" + reason + ")");
-
- // @TODO should this be moved to an exception handler of sorts. Somewhere errors are converted to correct execeptions.
- if (errorCode == AMQConstant.NO_CONSUMERS)
- {
- _connection.exceptionReceived(new AMQNoConsumersException("Error: " + reason, bouncedMessage, null));
- }
- else if (errorCode == AMQConstant.NO_ROUTE)
- {
- _connection.exceptionReceived(new AMQNoRouteException("Error: " + reason, bouncedMessage, null));
- }
- else
- {
- _connection.exceptionReceived(
- new AMQUndeliveredException(errorCode, "Error: " + reason, bouncedMessage, null));
- }
-
- }
- catch (Exception e)
- {
- _logger.error(
- "Caught exception trying to raise undelivered message exception (dump follows) - ignoring...",
- e);
- }
- }
- });
- }
-
/**
* Suspends or unsuspends this session.
*
@@ -2519,7 +2489,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
* should be unsuspended.
*
* @throws AMQException If the session cannot be suspended for any reason.
- *
* @todo Be aware of possible changes to parameter order as versions change.
*/
protected void suspendChannel(boolean suspend) throws AMQException // , FailoverException
@@ -2560,7 +2529,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
return getAMQConnection().getMaxPrefetch() > 0;
}
-
/** Signifies that the session has pending sends to commit. */
public void markDirty()
{
@@ -2571,7 +2539,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
public void markClean()
{
_dirty = false;
- _failedOver = false;
+ _failedOverDirty = false;
}
/**
@@ -2581,7 +2549,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
*/
public boolean hasFailedOver()
{
- return _failedOver;
+ return _failedOverDirty;
}
/**
@@ -2604,12 +2572,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
_flowControl.setFlowControl(active);
}
-
public void checkFlowControl() throws InterruptedException
{
- synchronized(_flowControl)
+ synchronized (_flowControl)
{
- while(!_flowControl.getFlowControl())
+ while (!_flowControl.getFlowControl())
{
_flowControl.wait();
}
@@ -2617,6 +2584,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
+ /** Used for debugging in the dispatcher. */
+ private static final Logger _dispatcherLogger = LoggerFactory.getLogger("org.apache.qpid.client.AMQSession.Dispatcher");
+
/** Responsible for decoding a message fragment and passing it to the appropriate message consumer. */
class Dispatcher extends Thread
@@ -2629,6 +2599,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
private final AtomicLong _rollbackMark = new AtomicLong(-1);
private String dispatcherID = "" + System.identityHashCode(this);
+
+
public Dispatcher()
{
super("Dispatcher-Channel-" + _channelId);
@@ -2647,7 +2619,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
- public void rejectPending(BasicMessageConsumer consumer)
+ public void rejectPending(C consumer)
{
synchronized (_lock)
{
@@ -2662,7 +2634,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
consumer.rollbackPendingMessages();
// Reject messages on pre-dispatch queue
- rejectMessagesForConsumerTag(consumer.getConsumerTag(), true);
+ rejectMessagesForConsumerTag(consumer.getConsumerTag(), true, false);
//Let the dispatcher deal with this when it gets to them.
// closeConsumer
@@ -2689,7 +2661,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
_dispatcherLogger.debug("Session Pre Dispatch Queue cleared");
- for (BasicMessageConsumer consumer : _consumers.values())
+ for (C consumer : _consumers.values())
{
if (!consumer.isNoConsume())
{
@@ -2755,7 +2727,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
_lock.wait();
}
- if (tagLE(deliveryTag, _rollbackMark.get()))
+ if (!(message instanceof CloseConsumerMessage)
+ && tagLE(deliveryTag, _rollbackMark.get()))
{
rejectMessage(message, true);
}
@@ -2816,8 +2789,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
//This if block is not needed anymore as bounce messages are handled separately
//if (message.getDeliverBody() != null)
//{
- final BasicMessageConsumer consumer =
- _consumers.get(message.getConsumerTag().toIntValue());
+ final C consumer =
+ _consumers.get(message.getConsumerTag());
if ((consumer == null) || consumer.isClosed())
{
@@ -2826,14 +2799,26 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
if (consumer == null)
{
_dispatcherLogger.info("Dispatcher(" + dispatcherID + ")Received a message(" + System.identityHashCode(message) + ")" + "["
- + message.getDeliveryTag() + "] from queue "
- + message.getConsumerTag() + " )without a handler - rejecting(requeue)...");
+ + message.getDeliveryTag() + "] from queue "
+ + message.getConsumerTag() + " )without a handler - rejecting(requeue)...");
}
else
{
- _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + "["
- + message.getDeliveryTag() + "] from queue " + " consumer("
- + message.getConsumerTag() + ") is closed rejecting(requeue)...");
+ if (consumer.isNoConsume())
+ {
+ _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + "["
+ + message.getDeliveryTag() + "] from queue " + " consumer("
+ + message.getConsumerTag() + ") is closed and a browser so dropping...");
+ //DROP MESSAGE
+ return;
+
+ }
+ else
+ {
+ _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + "["
+ + message.getDeliveryTag() + "] from queue " + " consumer("
+ + message.getConsumerTag() + ") is closed rejecting(requeue)...");
+ }
}
}
// Don't reject if we're already closing
@@ -2850,9 +2835,11 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
}
}
- abstract boolean tagLE(long tag1, long tag2);
+ protected abstract boolean tagLE(long tag1, long tag2);
+
+ protected abstract boolean updateRollbackMark(long current, long deliveryTag);
- abstract boolean updateRollbackMark(long current, long deliveryTag);
+ public abstract AMQMessageDelegateFactory getMessageDelegateFactory();
/*public void requestAccess(AMQShortString realm, boolean exclusive, boolean passive, boolean active, boolean write,
boolean read) throws AMQException
@@ -2880,9 +2867,9 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
private class SuspenderRunner implements Runnable
{
- private boolean _suspend;
+ private AtomicBoolean _suspend;
- public SuspenderRunner(boolean suspend)
+ public SuspenderRunner(AtomicBoolean suspend)
{
_suspend = suspend;
}
@@ -2891,7 +2878,10 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess
{
try
{
- suspendChannel(_suspend);
+ synchronized (_suspensionLock)
+ {
+ suspendChannel(_suspend.get());
+ }
}
catch (AMQException e)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
index 4c3d768020..aa0ff66545 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
@@ -27,17 +27,18 @@ import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import org.apache.qpid.client.message.FiledTableSupport;
+import org.apache.qpid.client.message.AMQMessageDelegateFactory;
import org.apache.qpid.util.Serial;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.transport.MessageCreditUnit;
-import org.apache.qpidity.transport.MessageFlowMode;
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Option;
-import org.apache.qpidity.transport.ExchangeBoundResult;
-import org.apache.qpidity.transport.Future;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.ErrorCode;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.transport.MessageCreditUnit;
+import org.apache.qpid.transport.MessageFlowMode;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Option;
+import org.apache.qpid.transport.ExchangeBoundResult;
+import org.apache.qpid.transport.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +52,7 @@ import java.util.Map;
/**
* This is a 0.10 Session
*/
-public class AMQSession_0_10 extends AMQSession
+public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, BasicMessageProducer_0_10>
{
/**
@@ -71,8 +72,11 @@ public class AMQSession_0_10 extends AMQSession
private Object _currentExceptionLock = new Object();
private QpidException _currentException;
- // a ref on the qpidity connection
- protected org.apache.qpidity.nclient.Connection _qpidConnection;
+ // a ref on the qpid connection
+ protected org.apache.qpid.nclient.Connection _qpidConnection;
+
+ private RangeSet unacked = new RangeSet();
+ private int unackedCount = 0;
/**
* USed to store the range of in tx messages
@@ -93,7 +97,7 @@ public class AMQSession_0_10 extends AMQSession
* @param defaultPrefetchLowMark The number of prefetched messages at which to resume the session.
* @param qpidConnection The qpid connection
*/
- AMQSession_0_10(org.apache.qpidity.nclient.Connection qpidConnection, AMQConnection con, int channelId,
+ AMQSession_0_10(org.apache.qpid.nclient.Connection qpidConnection, AMQConnection con, int channelId,
boolean transacted, int acknowledgeMode, MessageFactoryRegistry messageFactoryRegistry,
int defaultPrefetchHighMark, int defaultPrefetchLowMark)
{
@@ -123,7 +127,7 @@ public class AMQSession_0_10 extends AMQSession
* @param defaultPrefetchLow The number of prefetched messages at which to resume the session.
* @param qpidConnection The connection
*/
- AMQSession_0_10(org.apache.qpidity.nclient.Connection qpidConnection, AMQConnection con, int channelId,
+ AMQSession_0_10(org.apache.qpid.nclient.Connection qpidConnection, AMQConnection con, int channelId,
boolean transacted, int acknowledgeMode, int defaultPrefetchHigh, int defaultPrefetchLow)
{
@@ -131,6 +135,18 @@ public class AMQSession_0_10 extends AMQSession
defaultPrefetchHigh, defaultPrefetchLow);
}
+ private void addUnacked(int id)
+ {
+ unacked.add(id);
+ unackedCount++;
+ }
+
+ private void clearUnacked()
+ {
+ unacked.clear();
+ unackedCount = 0;
+ }
+
//------- overwritten methods of class AMQSession
/**
@@ -140,6 +156,7 @@ public class AMQSession_0_10 extends AMQSession
* @param multiple <tt>true</tt> to acknowledge all messages up to and including the one specified by the
* delivery tag, <tt>false</tt> to just acknowledge that message.
*/
+
public void acknowledgeMessage(long deliveryTag, boolean multiple)
{
if (_logger.isDebugEnabled())
@@ -147,14 +164,13 @@ public class AMQSession_0_10 extends AMQSession
_logger.debug("Sending ack for delivery tag " + deliveryTag + " on session " + _channelId);
}
// acknowledge this message
- RangeSet ranges = new RangeSet();
if (multiple)
{
for (Long messageTag : _unacknowledgedMessageTags)
{
if( messageTag <= deliveryTag )
{
- ranges.add((int) (long) messageTag);
+ addUnacked(messageTag.intValue());
_unacknowledgedMessageTags.remove(messageTag);
}
}
@@ -163,10 +179,26 @@ public class AMQSession_0_10 extends AMQSession
}
else
{
- ranges.add((int) deliveryTag);
+ addUnacked((int) deliveryTag);
_unacknowledgedMessageTags.remove(deliveryTag);
}
- getQpidSession().messageAcknowledge(ranges, _acknowledgeMode != org.apache.qpid.jms.Session.NO_ACKNOWLEDGE);
+
+ long prefetch = getAMQConnection().getMaxPrefetch();
+
+ if (unackedCount >= prefetch/2)
+ {
+ flushAcknowledgments();
+ }
+ }
+
+ void flushAcknowledgments()
+ {
+ if (unackedCount > 0)
+ {
+ getQpidSession().messageAcknowledge
+ (unacked, _acknowledgeMode != org.apache.qpid.jms.Session.NO_ACKNOWLEDGE);
+ clearUnacked();
+ }
}
/**
@@ -210,6 +242,7 @@ public class AMQSession_0_10 extends AMQSession
*/
public void sendClose(long timeout) throws AMQException, FailoverException
{
+ flushAcknowledgments();
getQpidSession().sync();
getQpidSession().close();
getCurrentException();
@@ -243,15 +276,16 @@ public class AMQSession_0_10 extends AMQSession
* @param durable If set when creating a new queue,
* the queue will be marked as durable.
* @param exclusive Exclusive queues can only be used from one connection at a time.
+ * @param arguments Exclusive queues can only be used from one connection at a time.
* @throws AMQException
* @throws FailoverException
*/
public void sendCreateQueue(AMQShortString name, final boolean autoDelete, final boolean durable,
- final boolean exclusive) throws AMQException, FailoverException
+ final boolean exclusive, Map<String, Object> arguments) throws AMQException, FailoverException
{
- getQpidSession().queueDeclare(name.toString(), null, null, durable ? Option.DURABLE : Option.NO_OPTION,
- autoDelete ? Option.AUTO_DELETE : Option.NO_OPTION,
- exclusive ? Option.EXCLUSIVE : Option.NO_OPTION);
+ getQpidSession().queueDeclare(name.toString(), null, arguments, durable ? Option.DURABLE : Option.NONE,
+ autoDelete ? Option.AUTO_DELETE : Option.NONE,
+ exclusive ? Option.EXCLUSIVE : Option.NONE);
// We need to sync so that we get notify of an error.
getQpidSession().sync();
getCurrentException();
@@ -311,7 +345,7 @@ public class AMQSession_0_10 extends AMQSession
/**
* Create an 0_10 message consumer
*/
- public BasicMessageConsumer createMessageConsumer(final AMQDestination destination, final int prefetchHigh,
+ public BasicMessageConsumer_0_10 createMessageConsumer(final AMQDestination destination, final int prefetchHigh,
final int prefetchLow, final boolean noLocal,
final boolean exclusive, String messageSelector,
final FieldTable ft, final boolean noConsume,
@@ -372,8 +406,8 @@ public class AMQSession_0_10 extends AMQSession
* This method is invoked when a consumer is creted
* Registers the consumer with the broker
*/
- public void sendConsume(BasicMessageConsumer consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler,
- boolean nowait, String messageSelector, AMQShortString tag)
+ public void sendConsume(BasicMessageConsumer_0_10 consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler,
+ boolean nowait, String messageSelector, int tag)
throws AMQException, FailoverException
{
boolean preAcquire;
@@ -382,32 +416,34 @@ public class AMQSession_0_10 extends AMQSession
preAcquire = ( ! consumer.isNoConsume() &&
(consumer.getMessageSelector() == null || consumer.getMessageSelector().equals("")) )
|| !(consumer.getDestination() instanceof AMQQueue);
- getQpidSession().messageSubscribe(queueName.toString(), tag.toString(),
+ getQpidSession().messageSubscribe(queueName.toString(), String.valueOf(tag),
getAcknowledgeMode() == NO_ACKNOWLEDGE ? Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED:Session.TRANSFER_CONFIRM_MODE_REQUIRED,
preAcquire ? Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE : Session.TRANSFER_ACQUIRE_MODE_NO_ACQUIRE,
- new MessagePartListenerAdapter((BasicMessageConsumer_0_10) consumer), null,
- consumer.isExclusive() ? Option.EXCLUSIVE : Option.NO_OPTION);
+ (BasicMessageConsumer_0_10) consumer, null,
+ consumer.isExclusive() ? Option.EXCLUSIVE : Option.NONE);
}
catch (JMSException e)
{
throw new AMQException(AMQConstant.INTERNAL_ERROR, "problem when registering consumer", e);
}
+ String consumerTag = ((BasicMessageConsumer_0_10)consumer).getConsumerTagString();
+
if (! prefetch())
{
- getQpidSession().messageSetFlowMode(consumer.getConsumerTag().toString(), MessageFlowMode.CREDIT);
+ getQpidSession().messageSetFlowMode(consumerTag, MessageFlowMode.CREDIT);
}
else
{
- getQpidSession().messageSetFlowMode(consumer.getConsumerTag().toString(), MessageFlowMode.WINDOW);
+ getQpidSession().messageSetFlowMode(consumerTag, MessageFlowMode.WINDOW);
}
- getQpidSession().messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.BYTE, 0xFFFFFFFF);
+ getQpidSession().messageFlow(consumerTag, MessageCreditUnit.BYTE, 0xFFFFFFFF);
// We need to sync so that we get notify of an error.
// only if not immediat prefetch
if(prefetch() && (consumer.isStrated() || _immediatePrefetch))
{
// set the flow
- getQpidSession().messageFlow(consumer.getConsumerTag().toString(),
+ getQpidSession().messageFlow(consumerTag,
MessageCreditUnit.MESSAGE,
getAMQConnection().getMaxPrefetch());
}
@@ -418,7 +454,7 @@ public class AMQSession_0_10 extends AMQSession
/**
* Create an 0_10 message producer
*/
- public BasicMessageProducer createMessageProducer(final Destination destination, final boolean mandatory,
+ public BasicMessageProducer_0_10 createMessageProducer(final Destination destination, final boolean mandatory,
final boolean immediate, final boolean waitUntilSent,
long producerId)
{
@@ -476,9 +512,9 @@ public class AMQSession_0_10 extends AMQSession
arguments.put("no-local", true);
}
getQpidSession().queueDeclare(res.toString(), null, arguments,
- amqd.isAutoDelete() ? Option.AUTO_DELETE : Option.NO_OPTION,
- amqd.isDurable() ? Option.DURABLE : Option.NO_OPTION,
- !amqd.isDurable() && amqd.isExclusive() ? Option.EXCLUSIVE : Option.NO_OPTION);
+ amqd.isAutoDelete() ? Option.AUTO_DELETE : Option.NONE,
+ amqd.isDurable() ? Option.DURABLE : Option.NONE,
+ !amqd.isDurable() && amqd.isExclusive() ? Option.EXCLUSIVE : Option.NONE);
// passive --> false
// We need to sync so that we get notify of an error.
getQpidSession().sync();
@@ -508,13 +544,14 @@ public class AMQSession_0_10 extends AMQSession
{
for (BasicMessageConsumer consumer : _consumers.values())
{
- getQpidSession().messageStop(consumer.getConsumerTag().toString());
+ getQpidSession().messageStop(String.valueOf(consumer.getConsumerTag()));
}
}
else
{
- for (BasicMessageConsumer consumer : _consumers.values())
+ for (BasicMessageConsumer_0_10 consumer : _consumers.values())
{
+ String consumerTag = String.valueOf(consumer.getConsumerTag());
//only set if msg list is null
try
{
@@ -522,18 +559,18 @@ public class AMQSession_0_10 extends AMQSession
{
if (consumer.getMessageListener() != null)
{
- getQpidSession().messageFlow(consumer.getConsumerTag().toString(),
+ getQpidSession().messageFlow(consumerTag,
MessageCreditUnit.MESSAGE, 1);
}
}
else
{
getQpidSession()
- .messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.MESSAGE,
+ .messageFlow(consumerTag, MessageCreditUnit.MESSAGE,
getAMQConnection().getMaxPrefetch());
}
getQpidSession()
- .messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.BYTE, 0xFFFFFFFF);
+ .messageFlow(consumerTag, MessageCreditUnit.BYTE, 0xFFFFFFFF);
}
catch (Exception e)
{
@@ -561,7 +598,7 @@ public class AMQSession_0_10 extends AMQSession
*
* @return The associated Qpid Session.
*/
- protected org.apache.qpidity.nclient.Session getQpidSession()
+ protected org.apache.qpid.nclient.Session getQpidSession()
{
return _qpidSession;
}
@@ -594,7 +631,7 @@ public class AMQSession_0_10 extends AMQSession
try
{
// this is done so that we can produce to a temporary queue beofre we create a consumer
- sendCreateQueue(result.getRoutingKey(), result.isAutoDelete(), result.isDurable(), result.isExclusive());
+ sendCreateQueue(result.getRoutingKey(), result.isAutoDelete(), result.isDurable(), result.isExclusive(),null);
sendQueueBind(result.getRoutingKey(), result.getRoutingKey(), new FieldTable(), result.getExchangeName(),result);
result.setQueueName(result.getRoutingKey());
}
@@ -612,7 +649,7 @@ public class AMQSession_0_10 extends AMQSession
/**
* Lstener for qpid protocol exceptions
*/
- private class QpidSessionExceptionListener implements org.apache.qpidity.nclient.ClosedListener
+ private class QpidSessionExceptionListener implements org.apache.qpid.nclient.ClosedListener
{
public void onClosed(ErrorCode errorCode, String reason, Throwable t)
{
@@ -681,7 +718,7 @@ public class AMQSession_0_10 extends AMQSession
AMQTopic origTopic=checkValidTopic(topic);
AMQTopic dest=AMQTopic.createDurable010Topic(origTopic, name, _connection);
- TopicSubscriberAdaptor subscriber=_subscriptions.get(name);
+ TopicSubscriberAdaptor<BasicMessageConsumer_0_10> subscriber=_subscriptions.get(name);
if (subscriber != null)
{
if (subscriber.getTopic().equals(topic))
@@ -732,7 +769,7 @@ public class AMQSession_0_10 extends AMQSession
}
}
- subscriber=new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createExclusiveConsumer(dest));
+ subscriber=new TopicSubscriberAdaptor(dest, createExclusiveConsumer(dest));
_subscriptions.put(name, subscriber);
_reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name);
@@ -740,7 +777,7 @@ public class AMQSession_0_10 extends AMQSession
return subscriber;
}
- Long requestQueueDepth(AMQDestination amqd)
+ protected Long requestQueueDepth(AMQDestination amqd)
{
return getQpidSession().queueQuery(amqd.getQueueName()).get().getMessageCount();
}
@@ -757,10 +794,11 @@ public class AMQSession_0_10 extends AMQSession
_txRangeSet.add((int) id);
_txSize++;
// this is a heuristic, we may want to have that configurable
- if( _txSize > _connection.getMaxPrefetch() / 2 )
+ if (_connection.getMaxPrefetch() == 1 ||
+ _connection.getMaxPrefetch() != 0 && _txSize % (_connection.getMaxPrefetch() / 2) == 0)
{
- // send completed so consumer credits don't dry up
- getQpidSession().messageAcknowledge(_txRangeSet, false);
+ // send completed so consumer credits don't dry up
+ getQpidSession().messageAcknowledge(_txRangeSet, false);
}
}
@@ -787,14 +825,19 @@ public class AMQSession_0_10 extends AMQSession
}
}
- final boolean tagLE(long tag1, long tag2)
+ protected final boolean tagLE(long tag1, long tag2)
{
return Serial.le((int) tag1, (int) tag2);
}
- final boolean updateRollbackMark(long currentMark, long deliveryTag)
+ protected final boolean updateRollbackMark(long currentMark, long deliveryTag)
{
return Serial.lt((int) currentMark, (int) deliveryTag);
}
+ public AMQMessageDelegateFactory getMessageDelegateFactory()
+ {
+ return AMQMessageDelegateFactory.FACTORY_0_10;
+ }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
index 00aa8e4d31..2442b157f1 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java
@@ -25,10 +25,12 @@ import javax.jms.*;
import javax.jms.IllegalStateException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQUndeliveredException;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.failover.FailoverRetrySupport;
-import org.apache.qpid.client.message.MessageFactoryRegistry;
+import org.apache.qpid.client.message.*;
+import org.apache.qpid.client.message.AMQMessageDelegateFactory;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.state.listener.SpecificMethodFrameListener;
import org.apache.qpid.common.AMQPFilterTypes;
@@ -40,7 +42,9 @@ import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public final class AMQSession_0_8 extends AMQSession
+import java.util.Map;
+
+public final class AMQSession_0_8 extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8>
{
/** Used for debugging. */
@@ -125,10 +129,19 @@ public final class AMQSession_0_8 extends AMQSession
handler.syncWrite(getProtocolHandler().getMethodRegistry().createTxCommitBody().generateFrame(_channelId), TxCommitOkBody.class);
}
- public void sendCreateQueue(AMQShortString name, final boolean autoDelete, final boolean durable, final boolean exclusive) throws AMQException,
+ public void sendCreateQueue(AMQShortString name, final boolean autoDelete, final boolean durable, final boolean exclusive, final Map<String, Object> arguments) throws AMQException,
FailoverException
{
- QueueDeclareBody body = getMethodRegistry().createQueueDeclareBody(getTicket(),name,false,durable,exclusive,autoDelete,false,null);
+ FieldTable table = null;
+ if(arguments != null && !arguments.isEmpty())
+ {
+ table = new FieldTable();
+ for(Map.Entry<String, Object> entry : arguments.entrySet())
+ {
+ table.setObject(entry.getKey(), entry.getValue());
+ }
+ }
+ QueueDeclareBody body = getMethodRegistry().createQueueDeclareBody(getTicket(),name,false,durable,exclusive,autoDelete,false,table);
AMQFrame queueDeclare = body.generateFrame(_channelId);
getProtocolHandler().syncWrite(queueDeclare, QueueDeclareOkBody.class);
}
@@ -206,6 +219,7 @@ public final class AMQSession_0_8 extends AMQSession
return isQueueBound(destination.getExchangeName(),destination.getAMQQueueName(),destination.getAMQQueueName());
}
+
public boolean isQueueBound(final AMQShortString exchangeName, final AMQShortString queueName, final AMQShortString routingKey)
throws JMSException
{
@@ -233,10 +247,14 @@ public final class AMQSession_0_8 extends AMQSession
{
throw new JMSAMQException("Queue bound query failed: " + e.getMessage(), e);
}
- }
-
- public void sendConsume(BasicMessageConsumer consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler, boolean nowait,
- String messageSelector, AMQShortString tag) throws AMQException, FailoverException
+ }
+
+ @Override public void sendConsume(BasicMessageConsumer_0_8 consumer,
+ AMQShortString queueName,
+ AMQProtocolHandler protocolHandler,
+ boolean nowait,
+ String messageSelector,
+ int tag) throws AMQException, FailoverException
{
FieldTable arguments = FieldTableFactory.newFieldTable();
if ((messageSelector != null) && !messageSelector.equals(""))
@@ -256,7 +274,7 @@ public final class AMQSession_0_8 extends AMQSession
BasicConsumeBody body = getMethodRegistry().createBasicConsumeBody(getTicket(),
queueName,
- tag,
+ new AMQShortString(String.valueOf(tag)),
consumer.isNoLocal(),
consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE,
consumer.isExclusive(),
@@ -314,18 +332,18 @@ public final class AMQSession_0_8 extends AMQSession
}
public BasicMessageConsumer_0_8 createMessageConsumer(final AMQDestination destination, final int prefetchHigh,
- final int prefetchLow, final boolean noLocal, final boolean exclusive, String messageSelector, final FieldTable ft,
+ final int prefetchLow, final boolean noLocal, final boolean exclusive, String messageSelector, final FieldTable arguments,
final boolean noConsume, final boolean autoClose) throws JMSException
{
final AMQProtocolHandler protocolHandler = getProtocolHandler();
return new BasicMessageConsumer_0_8(_channelId, _connection, destination, messageSelector, noLocal,
- _messageFactoryRegistry,this, protocolHandler, ft, prefetchHigh, prefetchLow,
+ _messageFactoryRegistry,this, protocolHandler, arguments, prefetchHigh, prefetchLow,
exclusive, _acknowledgeMode, noConsume, autoClose);
}
- public BasicMessageProducer createMessageProducer(final Destination destination, final boolean mandatory,
+ public BasicMessageProducer_0_8 createMessageProducer(final Destination destination, final boolean mandatory,
final boolean immediate, final boolean waitUntilSent, long producerId)
{
@@ -333,6 +351,66 @@ public final class AMQSession_0_8 extends AMQSession
this, getProtocolHandler(), producerId, immediate, mandatory, waitUntilSent);
}
+
+ @Override public void messageReceived(UnprocessedMessage message)
+ {
+
+ if (message instanceof ReturnMessage)
+ {
+ // Return of the bounced message.
+ returnBouncedMessage((ReturnMessage) message);
+ }
+ else
+ {
+ super.messageReceived(message);
+ }
+ }
+
+ private void returnBouncedMessage(final ReturnMessage msg)
+ {
+ _connection.performConnectionTask(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ // Bounced message is processed here, away from the mina thread
+ AbstractJMSMessage bouncedMessage =
+ _messageFactoryRegistry.createMessage(0, false, msg.getExchange(),
+ msg.getRoutingKey(), msg.getContentHeader(), msg.getBodies());
+ AMQConstant errorCode = AMQConstant.getConstant(msg.getReplyCode());
+ AMQShortString reason = msg.getReplyText();
+ _logger.debug("Message returned with error code " + errorCode + " (" + reason + ")");
+
+ // @TODO should this be moved to an exception handler of sorts. Somewhere errors are converted to correct execeptions.
+ if (errorCode == AMQConstant.NO_CONSUMERS)
+ {
+ _connection.exceptionReceived(new AMQNoConsumersException("Error: " + reason, bouncedMessage, null));
+ }
+ else if (errorCode == AMQConstant.NO_ROUTE)
+ {
+ _connection.exceptionReceived(new AMQNoRouteException("Error: " + reason, bouncedMessage, null));
+ }
+ else
+ {
+ _connection.exceptionReceived(
+ new AMQUndeliveredException(errorCode, "Error: " + reason, bouncedMessage, null));
+ }
+
+ }
+ catch (Exception e)
+ {
+ _logger.error(
+ "Caught exception trying to raise undelivered message exception (dump follows) - ignoring...",
+ e);
+ }
+ }
+ });
+ }
+
+
+
+
public void sendRollback() throws AMQException, FailoverException
{
TxRollbackBody body = getMethodRegistry().createTxRollbackBody();
@@ -353,7 +431,7 @@ public final class AMQSession_0_8 extends AMQSession
checkNotClosed();
AMQTopic origTopic = checkValidTopic(topic);
AMQTopic dest = AMQTopic.createDurableTopic(origTopic, name, _connection);
- TopicSubscriberAdaptor subscriber = _subscriptions.get(name);
+ TopicSubscriberAdaptor<BasicMessageConsumer_0_8> subscriber = _subscriptions.get(name);
if (subscriber != null)
{
if (subscriber.getTopic().equals(topic))
@@ -412,6 +490,28 @@ public final class AMQSession_0_8 extends AMQSession
return subscriber;
}
+
+
+
+ public void setPrefecthLimits(final int messagePrefetch, final long sizePrefetch) throws AMQException
+ {
+ new FailoverRetrySupport<Object, AMQException>(
+ new FailoverProtectedOperation<Object, AMQException>()
+ {
+ public Object execute() throws AMQException, FailoverException
+ {
+
+ BasicQosBody basicQosBody = getProtocolHandler().getMethodRegistry().createBasicQosBody(sizePrefetch, messagePrefetch, false);
+
+ // todo send low water mark when protocol allows.
+ // todo Be aware of possible changes to parameter order as versions change.
+ getProtocolHandler().syncWrite(basicQosBody.generateFrame(getChannelId()), BasicQosOkBody.class);
+
+ return null;
+ }
+ }, _connection).execute();
+ }
+
class QueueDeclareOkHandler extends SpecificMethodFrameListener
{
@@ -437,7 +537,7 @@ public final class AMQSession_0_8 extends AMQSession
}
- Long requestQueueDepth(AMQDestination amqd) throws AMQException, FailoverException
+ protected Long requestQueueDepth(AMQDestination amqd) throws AMQException, FailoverException
{
AMQFrame queueDeclare =
getMethodRegistry().createQueueDeclareBody(getTicket(),
@@ -449,18 +549,23 @@ public final class AMQSession_0_8 extends AMQSession
false,
null).generateFrame(_channelId);
QueueDeclareOkHandler okHandler = new QueueDeclareOkHandler();
- getProtocolHandler().writeCommandFrameAndWaitForReply(queueDeclare, okHandler);
+ getProtocolHandler().writeCommandFrameAndWaitForReply(queueDeclare, okHandler);
return okHandler._messageCount;
}
- final boolean tagLE(long tag1, long tag2)
+ protected final boolean tagLE(long tag1, long tag2)
{
return tag1 <= tag2;
}
- final boolean updateRollbackMark(long currentMark, long deliveryTag)
+ protected final boolean updateRollbackMark(long currentMark, long deliveryTag)
{
return false;
}
+ public AMQMessageDelegateFactory getMessageDelegateFactory()
+ {
+ return AMQMessageDelegateFactory.FACTORY_0_8;
+ }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index 8288581538..01bb68c23e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -22,9 +22,7 @@ package org.apache.qpid.client;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.failover.FailoverException;
-import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.MessageFactoryRegistry;
-import org.apache.qpid.client.message.UnprocessedMessage;
+import org.apache.qpid.client.message.*;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.*;
import org.apache.qpid.jms.MessageConsumer;
@@ -48,7 +46,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
-public abstract class BasicMessageConsumer<H, B> extends Closeable implements MessageConsumer
+public abstract class BasicMessageConsumer<U> extends Closeable implements MessageConsumer
{
private static final Logger _logger = LoggerFactory.getLogger(BasicMessageConsumer.class);
@@ -71,7 +69,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
private final AtomicReference<MessageListener> _messageListener = new AtomicReference<MessageListener>();
/** The consumer tag allows us to close the consumer by sending a jmsCancel method to the broker */
- protected AMQShortString _consumerTag;
+ protected int _consumerTag;
/** We need to know the channel id when constructing frames */
protected final int _channelId;
@@ -91,7 +89,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
/**
* We need to store the "raw" field table so that we can resubscribe in the event of failover being required
*/
- private final FieldTable _rawSelectorFieldTable;
+ private final FieldTable _arguments;
/**
* We store the high water prefetch field in order to be able to reuse it when resubscribing in the event of
@@ -168,7 +166,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
protected BasicMessageConsumer(int channelId, AMQConnection connection, AMQDestination destination,
String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory,
AMQSession session, AMQProtocolHandler protocolHandler,
- FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow,
+ FieldTable arguments, int prefetchHigh, int prefetchLow,
boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose)
{
_channelId = channelId;
@@ -179,7 +177,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
_messageFactory = messageFactory;
_session = session;
_protocolHandler = protocolHandler;
- _rawSelectorFieldTable = rawSelectorFieldTable;
+ _arguments = arguments;
_prefetchHigh = prefetchHigh;
_prefetchLow = prefetchLow;
_exclusive = exclusive;
@@ -277,6 +275,14 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
_messageListener.set(messageListener);
_session.setHasMessageListeners();
_session.startDispatcherIfNecessary();
+
+ // If we already have messages on the queue, deliver them to the listener
+ Object o = _synchronousQueue.poll();
+ while (o != null)
+ {
+ messageListener.onMessage((Message) o);
+ o = _synchronousQueue.poll();
+ }
}
}
}
@@ -335,9 +341,9 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
_receivingThread = null;
}
- public FieldTable getRawSelectorFieldTable()
+ public FieldTable getArguments()
{
- return _rawSelectorFieldTable;
+ return _arguments;
}
public int getPrefetch()
@@ -508,6 +514,12 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
throw e;
}
+ else if (o instanceof CloseConsumerMessage)
+ {
+ _closed.set(true);
+ deregisterConsumer();
+ return null;
+ }
else
{
return (AbstractJMSMessage) o;
@@ -562,6 +574,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
}
else
{
+ // FIXME: wow this is ugly
// //fixme this probably is not right
// if (!isNoConsume())
{ // done in BasicCancelOK Handler but not sending one so just deregister.
@@ -606,7 +619,8 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
}
else
{
- _closedStack = Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8);
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ _closedStack = Arrays.asList(stackTrace).subList(3, stackTrace.length - 1);
}
}
}
@@ -615,25 +629,56 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
}
/**
+ * @param closeMessage
+ * this message signals that we should close the browser
+ */
+ public void notifyCloseMessage(CloseConsumerMessage closeMessage)
+ {
+ if (isMessageListenerSet())
+ {
+ // Currently only possible to get this msg type with a browser.
+ // If we get the message here then we should probably just close
+ // this consumer.
+ // Though an AutoClose consumer with message listener is quite odd..
+ // Just log out the fact so we know where we are
+ _logger.warn("Using an AutoCloseconsumer with message listener is not supported.");
+ }
+ else
+ {
+ try
+ {
+ _synchronousQueue.put(closeMessage);
+ }
+ catch (InterruptedException e)
+ {
+ _logger.info(" SynchronousQueue.put interupted. Usually result of connection closing,"
+ + "but we shouldn't have close yet");
+ }
+ }
+ }
+
+
+ /**
* Called from the AMQSession when a message has arrived for this consumer. This methods handles both the case of a
* message listener or a synchronous receive() caller.
*
* @param messageFrame the raw unprocessed mesage
*/
- void notifyMessage(UnprocessedMessage messageFrame)
+ void notifyMessage(U messageFrame)
{
- final boolean debug = _logger.isDebugEnabled();
-
- if (debug)
+ if (messageFrame instanceof CloseConsumerMessage)
{
- _logger.debug("notifyMessage called with message number " + messageFrame.getDeliveryTag());
+ notifyCloseMessage((CloseConsumerMessage) messageFrame);
+ return;
}
+
+
try
{
- AbstractJMSMessage jmsMessage = createJMSMessageFromUnprocessedMessage(messageFrame);
+ AbstractJMSMessage jmsMessage = createJMSMessageFromUnprocessedMessage(_session.getMessageDelegateFactory(), messageFrame);
- if (debug)
+ if (_logger.isDebugEnabled())
{
_logger.debug("Message is of type: " + jmsMessage.getClass().getName());
}
@@ -668,7 +713,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
}
}
- public abstract AbstractJMSMessage createJMSMessageFromUnprocessedMessage(UnprocessedMessage<H, B> messageFrame)
+ public abstract AbstractJMSMessage createJMSMessageFromUnprocessedMessage(AMQMessageDelegateFactory delegateFactory, U messageFrame)
throws Exception;
/** @param jmsMessage this message has already been processed so can't redo preDeliver */
@@ -678,18 +723,9 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
{
if (isMessageListenerSet())
{
- // we do not need a lock around the test above, and the dispatch below as it is invalid
- // for an application to alter an installed listener while the session is started
- // synchronized (_closed)
- {
- // if (!_closed.get())
- {
-
- preApplicationProcessing(jmsMessage);
- getMessageListener().onMessage(jmsMessage);
- postDeliver(jmsMessage);
- }
- }
+ preApplicationProcessing(jmsMessage);
+ getMessageListener().onMessage(jmsMessage);
+ postDeliver(jmsMessage);
}
else
{
@@ -750,7 +786,7 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
{
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
}
-
+ _session.markDirty();
break;
case Session.DUPS_OK_ACKNOWLEDGE:
@@ -892,12 +928,12 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me
_session.deregisterConsumer(this);
}
- public AMQShortString getConsumerTag()
+ public int getConsumerTag()
{
return _consumerTag;
}
- public void setConsumerTag(AMQShortString consumerTag)
+ public void setConsumerTag(int consumerTag)
{
_consumerTag = consumerTag;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
index 9230225bd5..2a37298a43 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java
@@ -22,31 +22,24 @@ import org.slf4j.LoggerFactory;
import org.apache.qpid.client.message.*;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.AMQException;
-import org.apache.qpid.jms.*;
-import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.transport.*;
-import org.apache.qpidity.transport.Session;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.filter.MessageFilter;
-import org.apache.qpidity.filter.JMSSelectorFilter;
+import org.apache.qpid.transport.*;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.filter.MessageFilter;
+import org.apache.qpid.filter.JMSSelectorFilter;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.MessageListener;
-import java.io.IOException;
-import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* This is a 0.10 message consumer.
*/
-public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], ByteBuffer>
- implements org.apache.qpidity.nclient.util.MessageListener
+public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<UnprocessedMessage_0_10>
+ implements org.apache.qpid.nclient.MessagePartListener
{
/**
@@ -78,17 +71,18 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
* Specify whether this consumer is performing a sync receive
*/
private final AtomicBoolean _syncReceive = new AtomicBoolean(false);
+ private String _consumerTagString;
//--- constructor
protected BasicMessageConsumer_0_10(int channelId, AMQConnection connection, AMQDestination destination,
String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory,
AMQSession session, AMQProtocolHandler protocolHandler,
- FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow,
+ FieldTable arguments, int prefetchHigh, int prefetchLow,
boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose)
throws JMSException
{
super(channelId, connection, destination, messageSelector, noLocal, messageFactory, session, protocolHandler,
- rawSelectorFieldTable, prefetchHigh, prefetchLow, exclusive, acknowledgeMode, noConsume, autoClose);
+ arguments, prefetchHigh, prefetchLow, exclusive, acknowledgeMode, noConsume, autoClose);
_0_10session = (AMQSession_0_10) session;
if (messageSelector != null && !messageSelector.equals(""))
{
@@ -108,7 +102,20 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
_isStarted = connection.started();
}
- // ----- Interface org.apache.qpidity.client.util.MessageListener
+
+ @Override public void setConsumerTag(int consumerTag)
+ {
+ super.setConsumerTag(consumerTag);
+ _consumerTagString = String.valueOf(consumerTag);
+ }
+
+ public String getConsumerTagString()
+ {
+ return _consumerTagString;
+ }
+
+
+ // ----- Interface org.apache.qpid.client.util.MessageListener
/**
*
@@ -144,7 +151,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
{
if (isMessageListenerSet() && ! getSession().prefetch())
{
- _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(),
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
MessageCreditUnit.MESSAGE, 1);
}
_logger.debug("messageOk, trying to notify");
@@ -157,52 +164,19 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
/**
* This method is invoked by the transport layer when a message is delivered for this
* consumer. The message is transformed and pass to the session.
- * @param message an 0.10 message
+ * @param xfr an 0.10 message transfer
*/
- public void onMessage(Message message)
+ public void messageTransfer(MessageTransfer xfr)
+
+ //public void onMessage(Message message)
{
int channelId = getSession().getChannelId();
- long deliveryId = message.getMessageTransferId();
- AMQShortString consumerTag = getConsumerTag();
- AMQShortString exchange;
- AMQShortString routingKey;
- boolean redelivered = false;
- Struct[] headers = {message.getMessageProperties(), message.getDeliveryProperties()};
- if (headers[0] == null) {
- headers[0] = new MessageProperties();
- }
- if( message.getDeliveryProperties() != null )
- {
- exchange = new AMQShortString(message.getDeliveryProperties().getExchange());
- routingKey = new AMQShortString(message.getDeliveryProperties().getRoutingKey());
- redelivered = message.getDeliveryProperties().getRedelivered();
- }
- else
- {
- exchange = new AMQShortString("");
- routingKey = new AMQShortString("");
- headers[1] = new DeliveryProperties();
- }
+ int consumerTag = getConsumerTag();
+
UnprocessedMessage_0_10 newMessage =
- new UnprocessedMessage_0_10(channelId, deliveryId, consumerTag, exchange, routingKey, redelivered);
- try
- {
- newMessage.receiveBody(message.readData());
- }
- catch (IOException e)
- {
- getSession().getAMQConnection().exceptionReceived(e);
- }
- // if there is a replyto destination then we need to request the exchange info
- ReplyTo replyTo = ((MessageProperties) headers[0]).getReplyTo();
- if (replyTo != null && replyTo.getExchange() != null && !replyTo.getExchange().equals(""))
- {
- // <exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']*
- // the exchnage class will be set later from within the sesion thread
- String replyToUrl = replyTo.getExchange() + "/" + replyTo.getRoutingKey() + "/" + replyTo.getRoutingKey();
- newMessage.setReplyToURL(replyToUrl);
- }
- newMessage.setContentHeader(headers);
+ new UnprocessedMessage_0_10(consumerTag, xfr);
+
+
getSession().messageReceived(newMessage);
// else ignore this message
}
@@ -215,47 +189,16 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
*/
@Override void sendCancel() throws AMQException
{
- ((AMQSession_0_10) getSession()).getQpidSession().messageCancel(getConsumerTag().toString());
+ ((AMQSession_0_10) getSession()).getQpidSession().messageCancel(getConsumerTagString());
((AMQSession_0_10) getSession()).getQpidSession().sync();
// confirm cancel
getSession().confirmConsumerCancelled(getConsumerTag());
((AMQSession_0_10) getSession()).getCurrentException();
}
- @Override void notifyMessage(UnprocessedMessage messageFrame)
+ @Override void notifyMessage(UnprocessedMessage_0_10 messageFrame)
{
- // if there is a replyto destination then we need to request the exchange info
- String replyToURL = messageFrame.getReplyToURL();
- if (replyToURL != null && !replyToURL.equals(""))
- {
- AMQShortString shortExchangeName = new AMQShortString( replyToURL.substring(0, replyToURL.indexOf('/')));
- String replyToUrl = "://" + replyToURL;
- if (shortExchangeName.equals(ExchangeDefaults.TOPIC_EXCHANGE_NAME))
- {
- replyToUrl = ExchangeDefaults.TOPIC_EXCHANGE_CLASS + replyToUrl;
- }
- else if (shortExchangeName.equals(ExchangeDefaults.DIRECT_EXCHANGE_NAME))
- {
- replyToUrl = ExchangeDefaults.DIRECT_EXCHANGE_CLASS + replyToUrl;
- }
- else if (shortExchangeName.equals(ExchangeDefaults.HEADERS_EXCHANGE_NAME))
- {
- replyToUrl = ExchangeDefaults.HEADERS_EXCHANGE_CLASS + replyToUrl;
- }
- else if (shortExchangeName.equals(ExchangeDefaults.FANOUT_EXCHANGE_NAME))
- {
- replyToUrl = ExchangeDefaults.FANOUT_EXCHANGE_CLASS + replyToUrl;
- }
- else
- {
- Future<ExchangeQueryResult> future =
- ((AMQSession_0_10) getSession()).getQpidSession().exchangeQuery(shortExchangeName.toString());
- ExchangeQueryResult res = future.get();
- // <exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']*
- replyToUrl = res.getType() + replyToUrl;
- }
- ((UnprocessedMessage_0_10) messageFrame).setReplyToURL(replyToUrl);
- }
+
super.notifyMessage(messageFrame);
}
@@ -269,12 +212,10 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
}
@Override public AbstractJMSMessage createJMSMessageFromUnprocessedMessage(
- UnprocessedMessage<Struct[], ByteBuffer> messageFrame) throws Exception
+ AMQMessageDelegateFactory delegateFactory, UnprocessedMessage_0_10 msg) throws Exception
{
- return _messageFactory.createMessage(messageFrame.getDeliveryTag(), messageFrame.isRedelivered(),
- messageFrame.getExchange(), messageFrame.getRoutingKey(),
- messageFrame.getContentHeader(), messageFrame.getBodies(),
- messageFrame.getReplyToURL());
+ AMQMessageDelegate_0_10.updateExchangeTypeMapping(msg.getMessageTransfer().getHeader(), ((AMQSession_0_10)getSession()).getQpidSession());
+ return _messageFactory.createMessage(msg.getMessageTransfer());
}
// private methods
@@ -330,7 +271,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
// and messages are not prefetched we then need to request another one
if(! getSession().prefetch())
{
- _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(),
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
MessageCreditUnit.MESSAGE, 1);
}
}
@@ -418,7 +359,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
super.setMessageListener(messageListener);
if (messageListener != null && ! getSession().prefetch())
{
- _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(),
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
MessageCreditUnit.MESSAGE, 1);
}
if (messageListener != null && !_synchronousQueue.isEmpty())
@@ -443,7 +384,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
_isStarted = true;
if (_syncReceive.get())
{
- _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(),
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
MessageCreditUnit.MESSAGE, 1);
}
}
@@ -466,7 +407,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
{
if (isStrated() && ! getSession().prefetch() && _synchronousQueue.isEmpty())
{
- _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(),
+ _0_10session.getQpidSession().messageFlow(getConsumerTagString(),
MessageCreditUnit.MESSAGE, 1);
}
if (! getSession().prefetch())
@@ -489,4 +430,5 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
}
}
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
index 5414e25539..494a8fb43d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java
@@ -20,40 +20,48 @@
*/
package org.apache.qpid.client;
-import java.util.concurrent.TimeUnit;
+import javax.jms.InvalidSelectorException;
+import javax.jms.JMSException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.failover.FailoverException;
-import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.MessageFactoryRegistry;
-import org.apache.qpid.client.message.UnprocessedMessage;
+import org.apache.qpid.client.message.*;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.BasicCancelBody;
-import org.apache.qpid.framing.BasicCancelOkBody;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.filter.JMSSelectorFilter;
+import org.apache.qpid.framing.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<ContentHeaderBody,ContentBody>
+public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMessage_0_8>
{
protected final Logger _logger = LoggerFactory.getLogger(getClass());
protected BasicMessageConsumer_0_8(int channelId, AMQConnection connection, AMQDestination destination,
String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session,
- AMQProtocolHandler protocolHandler, FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow,
- boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose)
+ AMQProtocolHandler protocolHandler, FieldTable arguments, int prefetchHigh, int prefetchLow,
+ boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose) throws JMSException
{
super(channelId, connection, destination,messageSelector,noLocal,messageFactory,session,
- protocolHandler, rawSelectorFieldTable, prefetchHigh, prefetchLow, exclusive,
+ protocolHandler, arguments, prefetchHigh, prefetchLow, exclusive,
acknowledgeMode, noConsume, autoClose);
+ try
+ {
+
+ if (messageSelector != null && messageSelector.length() > 0)
+ {
+ JMSSelectorFilter _filter = new JMSSelectorFilter(messageSelector);
+ }
+ }
+ catch (QpidException e)
+ {
+ throw new InvalidSelectorException("cannot create consumer because of selector issue");
+ }
}
void sendCancel() throws AMQException, FailoverException
{
- BasicCancelBody body = getSession().getMethodRegistry().createBasicCancelBody(_consumerTag, false);
+ BasicCancelBody body = getSession().getMethodRegistry().createBasicCancelBody(new AMQShortString(String.valueOf(_consumerTag)), false);
final AMQFrame cancelFrame = body.generateFrame(_channelId);
@@ -65,7 +73,7 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<ContentHeader
}
}
- public AbstractJMSMessage createJMSMessageFromUnprocessedMessage(UnprocessedMessage<ContentHeaderBody, ContentBody> messageFrame)throws Exception
+ public AbstractJMSMessage createJMSMessageFromUnprocessedMessage(AMQMessageDelegateFactory delegateFactory, UnprocessedMessage_0_8 messageFrame)throws Exception
{
return _messageFactory.createMessage(messageFrame.getDeliveryTag(),
@@ -74,4 +82,4 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<ContentHeader
}
-} \ No newline at end of file
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index 9d01fbfaa2..beaa47ed1e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -31,23 +31,16 @@ import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.ObjectMessage;
-import javax.jms.Queue;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
-import javax.jms.Topic;
-import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.client.message.MessageConverter;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.BasicPublishBody;
-import org.apache.qpid.framing.CompositeAMQDataBlock;
import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.ExchangeDeclareBody;
+import org.apache.qpid.util.UUIDGen;
+import org.apache.qpid.util.UUIDs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -122,6 +115,8 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
private boolean _disableMessageId;
+ private UUIDGen _messageIdGenerator = UUIDs.newGenerator();
+
private static final ContentBody[] NO_CONTENT_BODIES = new ContentBody[0];
protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
@@ -365,27 +360,27 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
if (message instanceof BytesMessage)
{
- newMessage = new MessageConverter((BytesMessage) message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, (BytesMessage) message).getConvertedMessage();
}
else if (message instanceof MapMessage)
{
- newMessage = new MessageConverter((MapMessage) message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, (MapMessage) message).getConvertedMessage();
}
else if (message instanceof ObjectMessage)
{
- newMessage = new MessageConverter((ObjectMessage) message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, (ObjectMessage) message).getConvertedMessage();
}
else if (message instanceof TextMessage)
{
- newMessage = new MessageConverter((TextMessage) message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, (TextMessage) message).getConvertedMessage();
}
else if (message instanceof StreamMessage)
{
- newMessage = new MessageConverter((StreamMessage) message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, (StreamMessage) message).getConvertedMessage();
}
else
{
- newMessage = new MessageConverter(message).getConvertedMessage();
+ newMessage = new MessageConverter(_session, message).getConvertedMessage();
}
if (newMessage != null)
@@ -453,19 +448,18 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
}
}
+ UUID messageId = null;
if (_disableMessageId)
{
- message.setJMSMessageID(null);
+ message.setJMSMessageID((UUID)null);
}
else
{
- StringBuilder b = new StringBuilder(39);
- b.append("ID:");
- b.append(UUID.randomUUID());
- message.setJMSMessageID(b.toString());
+ messageId = _messageIdGenerator.generate();
+ message.setJMSMessageID(messageId);
}
- sendMessage(destination, origMessage, message, deliveryMode, priority, timeToLive, mandatory, immediate, wait);
+ sendMessage(destination, origMessage, message, messageId, deliveryMode, priority, timeToLive, mandatory, immediate, wait);
if (message != origMessage)
{
@@ -484,8 +478,8 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac
}
abstract void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
- int deliveryMode, int priority, long timeToLive, boolean mandatory,
- boolean immediate, boolean wait)throws JMSException;
+ UUID messageId, int deliveryMode, int priority, long timeToLive, boolean mandatory,
+ boolean immediate, boolean wait) throws JMSException;
private void checkTemporaryDestination(AMQDestination destination) throws JMSException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
index 5eb066ec36..02c5526e03 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java
@@ -22,6 +22,7 @@ import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import java.nio.ByteBuffer;
import javax.jms.JMSException;
import javax.jms.Message;
@@ -29,17 +30,15 @@ import javax.jms.DeliveryMode;
import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.client.message.FiledTableSupport;
+import org.apache.qpid.client.message.AMQMessageDelegate_0_10;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.url.AMQBindingURL;
-import org.apache.qpidity.nclient.util.ByteBufferMessage;
-import org.apache.qpidity.njms.ExceptionHelper;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageDeliveryMode;
-import org.apache.qpidity.transport.MessageDeliveryPriority;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.ReplyTo;
+import org.apache.qpid.nclient.util.ByteBufferMessage;
+import org.apache.qpid.njms.ExceptionHelper;
+import org.apache.qpid.transport.*;
+import static org.apache.qpid.transport.Option.*;
/**
* This is a 0_10 message producer.
@@ -68,23 +67,25 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
* Sends a message to a given destination
*/
void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
- int deliveryMode, int priority, long timeToLive, boolean mandatory, boolean immediate,
- boolean wait) throws JMSException
+ UUID messageId, int deliveryMode, int priority, long timeToLive, boolean mandatory,
+ boolean immediate, boolean wait) throws JMSException
{
message.prepareForSending();
- if (message.get010Message() == null)
+
+ AMQMessageDelegate_0_10 delegate = (AMQMessageDelegate_0_10) message.getDelegate();
+
+ DeliveryProperties deliveryProp = delegate.getDeliveryProperties();
+ MessageProperties messageProps = delegate.getMessageProperties();
+
+ if (messageId != null)
{
- message.set010Message(new ByteBufferMessage());
+ messageProps.setMessageId(messageId);
}
- // force a rebuild of the 0-10 message if data has changed
- if (message.getData() == null)
+ else if (messageProps.hasMessageId())
{
- message.dataChanged();
+ messageProps.clearMessageId();
}
- DeliveryProperties deliveryProp = message.get010Message().getDeliveryProperties();
- MessageProperties messageProps = message.get010Message().getMessageProperties();
- // set the delivery properties
if (!_disableTimestamps)
{
final long currentTime = System.currentTimeMillis();
@@ -124,10 +125,10 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
deliveryProp.setPriority(MessageDeliveryPriority.get((short) priority));
message.setJMSPriority(priority);
}
- String excahngeName = destination.getExchangeName().toString();
- if ( deliveryProp.getExchange() == null || ! deliveryProp.getExchange().equals(excahngeName))
+ String exchangeName = destination.getExchangeName().toString();
+ if ( deliveryProp.getExchange() == null || ! deliveryProp.getExchange().equals(exchangeName))
{
- deliveryProp.setExchange(excahngeName);
+ deliveryProp.setExchange(exchangeName);
}
String routingKey = destination.getRoutingKey().toString();
if (deliveryProp.getRoutingKey() == null || ! deliveryProp.getRoutingKey().equals(routingKey))
@@ -135,105 +136,29 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer
deliveryProp.setRoutingKey(routingKey);
}
- BasicContentHeaderProperties contentHeaderProperties = message.getContentHeaderProperties();
- if (contentHeaderProperties.reset())
- {
- // set the application properties
- messageProps.setContentType(contentHeaderProperties.getContentType().toString());
- messageProps.setContentLength(message.getContentLength());
-
- // XXX: fixme
- String mid = message.getJMSMessageID();
- if( mid != null )
- {
- messageProps.setMessageId(UUID.fromString(mid.substring(3)));
- }
-
- AMQShortString correlationID = contentHeaderProperties.getCorrelationId();
- if (correlationID != null)
- {
- messageProps.setCorrelationId(correlationID.getBytes());
- }
-
- String replyToURL = contentHeaderProperties.getReplyToAsString();
- if (replyToURL != null)
- {
- if(_logger.isDebugEnabled())
- {
- StringBuffer b = new StringBuffer();
- b.append("\n==========================");
- b.append("\nReplyTo : " + replyToURL);
- b.append("\n==========================");
- _logger.debug(b.toString());
- }
- AMQBindingURL dest;
- try
- {
- dest = new AMQBindingURL(replyToURL);
- }
- catch (URISyntaxException e)
- {
- throw ExceptionHelper.convertQpidExceptionToJMSException(e);
- }
- messageProps.setReplyTo(new ReplyTo(dest.getExchangeName().toString(), dest.getRoutingKey().toString()));
- }
-
- Map<String,Object> map = null;
-
- if (contentHeaderProperties.getHeaders() != null)
- {
- //JMS_QPID_DESTTYPE is always set but useles so this is a temporary fix
- contentHeaderProperties.getHeaders().remove(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName());
- map = FiledTableSupport.convertToMap(contentHeaderProperties.getHeaders());
- }
-
- AMQShortString type = contentHeaderProperties.getType();
- if (type != null)
- {
- if (map == null)
- {
- map = new HashMap<String,Object>();
- }
- map.put(AbstractJMSMessage.JMS_TYPE, type.toString());
- }
-
- if (map != null)
- {
- messageProps.setApplicationHeaders(map);
- }
- }
+ messageProps.setContentLength(message.getContentLength());
// send the message
try
{
- org.apache.qpidity.nclient.Session ssn = ((AMQSession_0_10) getSession()).getQpidSession();
+ org.apache.qpid.transport.Session ssn = (org.apache.qpid.transport.Session)
+ ((AMQSession_0_10) getSession()).getQpidSession();
// if true, we need to sync the delivery of this message
boolean sync = (deliveryMode == DeliveryMode.PERSISTENT &&
getSession().getAMQConnection().getSyncPersistence());
+ org.apache.mina.common.ByteBuffer data = message.getData();
+ ByteBuffer buffer = data == null ? ByteBuffer.allocate(0) : data.buf().slice();
+
+ ssn.messageTransfer(destination.getExchangeName().toString(), MessageAcceptMode.NONE,
+ MessageAcquireMode.PRE_ACQUIRED,
+ new Header(deliveryProp, messageProps),
+ buffer, sync ? SYNC : NONE);
if (sync)
{
- ssn.setAutoSync(true);
- }
- try
- {
- ssn.messageTransfer(destination.getExchangeName().toString(),
- message.get010Message(),
- ssn.TRANSFER_CONFIRM_MODE_NOT_REQUIRED,
- ssn.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE);
+ ssn.sync();
}
- finally
- {
- if (sync)
- {
- ssn.setAutoSync(false);
- }
- }
- }
- catch (IOException e)
- {
- throw ExceptionHelper.convertQpidExceptionToJMSException(e);
}
catch (RuntimeException rte)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
index ff991b1a03..c547fcb488 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_8.java
@@ -20,11 +20,15 @@
*/
package org.apache.qpid.client;
+import java.util.UUID;
+
import javax.jms.JMSException;
import javax.jms.Message;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.client.message.AbstractJMSMessage;
+import org.apache.qpid.client.message.AMQMessageDelegate;
+import org.apache.qpid.client.message.AMQMessageDelegate_0_8;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.BasicConsumeBody;
@@ -65,9 +69,9 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
_protocolHandler.writeFrame(declare);
}
- void sendMessage(AMQDestination destination, Message origMessage,AbstractJMSMessage message,
- int deliveryMode,int priority, long timeToLive, boolean mandatory, boolean immediate,
- boolean wait) throws JMSException
+ void sendMessage(AMQDestination destination, Message origMessage, AbstractJMSMessage message,
+ UUID messageId, int deliveryMode,int priority, long timeToLive, boolean mandatory,
+ boolean immediate, boolean wait) throws JMSException
{
BasicPublishBody body = getSession().getMethodRegistry().createBasicPublishBody(_session.getTicket(),
destination.getExchangeName(),
@@ -79,7 +83,8 @@ public class BasicMessageProducer_0_8 extends BasicMessageProducer
message.prepareForSending();
ByteBuffer payload = message.getData();
- BasicContentHeaderProperties contentHeaderProperties = message.getContentHeaderProperties();
+ AMQMessageDelegate_0_8 delegate = (AMQMessageDelegate_0_8) message.getDelegate();
+ BasicContentHeaderProperties contentHeaderProperties = delegate.getContentHeaderProperties();
if (!_disableTimestamps)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java b/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
index 29fa03fd1d..9bdef22f96 100644
--- a/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
+++ b/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
@@ -32,20 +32,20 @@ import javax.jms.TopicSubscriber;
* Wraps a MessageConsumer to fulfill the extended TopicSubscriber contract
*
*/
-class TopicSubscriberAdaptor implements TopicSubscriber
+class TopicSubscriberAdaptor<C extends BasicMessageConsumer> implements TopicSubscriber
{
private final Topic _topic;
- private final BasicMessageConsumer _consumer;
+ private final C _consumer;
private final boolean _noLocal;
- TopicSubscriberAdaptor(Topic topic, BasicMessageConsumer consumer, boolean noLocal)
+ TopicSubscriberAdaptor(Topic topic, C consumer, boolean noLocal)
{
_topic = topic;
_consumer = consumer;
_noLocal = noLocal;
}
- TopicSubscriberAdaptor(Topic topic, BasicMessageConsumer consumer)
+ TopicSubscriberAdaptor(Topic topic, C consumer)
{
this(topic, consumer, consumer.isNoLocal());
}
@@ -103,7 +103,7 @@ class TopicSubscriberAdaptor implements TopicSubscriber
}
private void checkPreConditions() throws javax.jms.IllegalStateException{
- BasicMessageConsumer msgConsumer = (BasicMessageConsumer)_consumer;
+ C msgConsumer = _consumer;
if (msgConsumer.isClosed() ){
throw new javax.jms.IllegalStateException("Consumer is closed");
@@ -120,7 +120,7 @@ class TopicSubscriberAdaptor implements TopicSubscriber
}
}
- BasicMessageConsumer getMessageConsumer()
+ C getMessageConsumer()
{
return _consumer;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
index 7a107d748b..6763c72ecd 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java
@@ -21,9 +21,9 @@ import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.dtx.XidImpl;
-import org.apache.qpidity.transport.*;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.dtx.XidImpl;
+import org.apache.qpid.transport.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -76,7 +76,7 @@ public class XAResourceImpl implements XAResource
_logger.debug("commit tx branch with xid: ", xid);
}
Future<XaResult> future =
- _xaSession.getQpidSession().dtxCommit(convertXid(xid), b ? Option.ONE_PHASE : Option.NO_OPTION);
+ _xaSession.getQpidSession().dtxCommit(convertXid(xid), b ? Option.ONE_PHASE : Option.NONE);
// now wait on the future for the result
XaResult result = null;
@@ -86,7 +86,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -127,10 +127,11 @@ public class XAResourceImpl implements XAResource
default:
throw new XAException(XAException.XAER_INVAL);
}
+ _xaSession.flushAcknowledgments();
Future<XaResult> future = _xaSession.getQpidSession()
.dtxEnd(convertXid(xid),
- flag == XAResource.TMFAIL ? Option.FAIL : Option.NO_OPTION,
- flag == XAResource.TMSUSPEND ? Option.SUSPEND : Option.NO_OPTION);
+ flag == XAResource.TMFAIL ? Option.FAIL : Option.NONE,
+ flag == XAResource.TMSUSPEND ? Option.SUSPEND : Option.NONE);
// now wait on the future for the result
XaResult result = null;
try
@@ -139,7 +140,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -168,7 +169,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -198,7 +199,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -245,7 +246,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -288,7 +289,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr( e.getExceptions().get(0).getErrorCode());
@@ -297,7 +298,7 @@ public class XAResourceImpl implements XAResource
int i = 0;
for (Object obj : res.getInDoubt())
{
- org.apache.qpidity.transport.Xid xid = (org.apache.qpidity.transport.Xid) obj;
+ org.apache.qpid.transport.Xid xid = (org.apache.qpid.transport.Xid) obj;
result[i] = new XidImpl(xid.getBranchId(), (int) xid.getFormat(), xid.getGlobalId());
i++;
}
@@ -326,7 +327,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr( e.getExceptions().get(0).getErrorCode());
@@ -400,8 +401,8 @@ public class XAResourceImpl implements XAResource
}
Future<XaResult> future = _xaSession.getQpidSession()
.dtxStart(convertXid(xid),
- flag == XAResource.TMJOIN ? Option.JOIN : Option.NO_OPTION,
- flag == XAResource.TMRESUME ? Option.RESUME : Option.NO_OPTION);
+ flag == XAResource.TMJOIN ? Option.JOIN : Option.NONE,
+ flag == XAResource.TMRESUME ? Option.RESUME : Option.NONE);
// now wait on the future for the result
XaResult result = null;
try
@@ -410,7 +411,7 @@ public class XAResourceImpl implements XAResource
}
catch (SessionException e)
{
- // we need to restore the qpidity session that has been closed
+ // we need to restore the qpid session that has been closed
_xaSession.createSession();
// we should get a single exception
convertExecutionErrorToXAErr(e.getExceptions().get(0).getErrorCode());
@@ -511,7 +512,7 @@ public class XAResourceImpl implements XAResource
* @return the qpid formated xid
* @throws XAException when xid is null or when it cannot be converted.
*/
- private org.apache.qpidity.transport.Xid convertXid(Xid xid) throws XAException
+ private org.apache.qpid.transport.Xid convertXid(Xid xid) throws XAException
{
if (xid == null)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java b/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
index 1eda71cc63..51b4b7899f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/XASessionImpl.java
@@ -17,7 +17,7 @@
*/
package org.apache.qpid.client;
-import org.apache.qpidity.nclient.DtxSession;
+import org.apache.qpid.nclient.DtxSession;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import javax.jms.*;
@@ -48,7 +48,7 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
/**
* Create a JMS XASession
*/
- public XASessionImpl(org.apache.qpidity.nclient.Connection qpidConnection, AMQConnection con, int channelId,
+ public XASessionImpl(org.apache.qpid.nclient.Connection qpidConnection, AMQConnection con, int channelId,
int defaultPrefetchHigh, int defaultPrefetchLow)
{
super(qpidConnection, con, channelId, false, // this is not a transacted session
@@ -61,7 +61,7 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
//-- public methods
/**
- * Create a qpidity session.
+ * Create a qpid session.
*/
public void createSession()
{
@@ -126,7 +126,7 @@ public class XASessionImpl extends AMQSession_0_10 implements XASession, XATopic
*
* @return The associated Qpid Session.
*/
- protected org.apache.qpidity.nclient.DtxSession getQpidSession()
+ protected org.apache.qpid.nclient.DtxSession getQpidSession()
{
return _qpidDtxSession;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
index 76c899f565..927f660932 100644
--- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java
@@ -139,11 +139,15 @@ public class FailoverHandler implements Runnable
// have a state waiter waiting until the connection is closed for some reason. Or in future we may have
// a slightly more complex state model therefore I felt it was worthwhile doing this.
AMQStateManager existingStateManager = _amqProtocolHandler.getStateManager();
- _amqProtocolHandler.setStateManager(new AMQStateManager(_amqProtocolHandler.getProtocolSession()));
+
+ _amqProtocolHandler.setStateManager(new AMQStateManager());
+
+
if (!_amqProtocolHandler.getConnection().firePreFailover(_host != null))
{
_logger.info("Failover process veto-ed by client");
+ //Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);
//todo: ritchiem these exceptions are useless... Would be better to attempt to propogate exception that
@@ -181,13 +185,19 @@ public class FailoverHandler implements Runnable
if (!failoverSucceeded)
{
+ //Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);
+
_amqProtocolHandler.getConnection().exceptionReceived(
new AMQDisconnectedException("Server closed connection and no failover " +
"was successful", null));
}
else
{
+ // Set the new Protocol Session in the StateManager.
+ existingStateManager.setProtocolSession(_amqProtocolHandler.getProtocolSession());
+
+ //Restore Existing State Manager
_amqProtocolHandler.setStateManager(existingStateManager);
try
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
index 5bd36aa88b..365fed6aa5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
@@ -5,14 +5,8 @@ import org.slf4j.LoggerFactory;
import org.apache.qpid.framing.*;
import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQInvalidRoutingKeyException;
-import org.apache.qpid.AMQChannelClosedException;
-import org.apache.qpid.protocol.AMQConstant;
public class AccessRequestOkMethodHandler implements StateAwareMethodListener<AccessRequestOkBody>
{
@@ -25,11 +19,10 @@ public class AccessRequestOkMethodHandler implements StateAwareMethodListener<Ac
return _handler;
}
- public void methodReceived(AMQStateManager stateManager, AccessRequestOkBody method, int channelId)
+ public void methodReceived(AMQProtocolSession session, AccessRequestOkBody method, int channelId)
throws AMQException
{
_logger.debug("AccessRequestOk method received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
session.setTicket(method.getTicket(), channelId);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java
index e3e08667d8..5cb9412d51 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java
@@ -22,11 +22,8 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.BasicCancelOkBody;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,13 +42,9 @@ public class BasicCancelOkMethodHandler implements StateAwareMethodListener<Basi
private BasicCancelOkMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, BasicCancelOkBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, BasicCancelOkBody body, int channelId)
throws AMQException
{
- AMQProtocolSession session = stateManager.getProtocolSession();
-
-
-
if (_logger.isInfoEnabled())
{
_logger.info("New BasicCancelOk method received for consumer:" + body.getConsumerTag());
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java
index 4deaa314ec..6237234c4d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java
@@ -21,10 +21,8 @@
package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.message.UnprocessedMessage;
import org.apache.qpid.client.message.UnprocessedMessage_0_8;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.BasicDeliverBody;
import org.slf4j.Logger;
@@ -41,18 +39,16 @@ public class BasicDeliverMethodHandler implements StateAwareMethodListener<Basic
return _instance;
}
- public void methodReceived(AMQStateManager stateManager, BasicDeliverBody body, int channelId)
- throws AMQException
+ public void methodReceived(AMQProtocolSession session, BasicDeliverBody body, int channelId)
+ throws AMQException
{
- final AMQProtocolSession session = stateManager.getProtocolSession();
final UnprocessedMessage_0_8 msg = new UnprocessedMessage_0_8(
- channelId,
body.getDeliveryTag(),
- body.getConsumerTag(),
+ body.getConsumerTag().toIntValue(),
body.getExchange(),
body.getRoutingKey(),
body.getRedelivered());
- _logger.debug("New JmsDeliver method received");
- session.unprocessedMessageReceived(msg);
+ _logger.debug("New JmsDeliver method received:" + session);
+ session.unprocessedMessageReceived(channelId, msg);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java
index 682c3ac2c1..3bbc9209c5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java
@@ -22,13 +22,9 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.ReturnMessage;
-import org.apache.qpid.client.message.UnprocessedMessage;
-import org.apache.qpid.client.message.UnprocessedMessage_0_8;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.BasicReturnBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,19 +41,18 @@ public class BasicReturnMethodHandler implements StateAwareMethodListener<BasicR
}
- public void methodReceived(AMQStateManager stateManager, BasicReturnBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, BasicReturnBody body, int channelId)
throws AMQException
{
_logger.debug("New JmsBounce method received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
- final ReturnMessage msg = new ReturnMessage(channelId,
+ final ReturnMessage msg = new ReturnMessage(
body.getExchange(),
body.getRoutingKey(),
body.getReplyText(),
body.getReplyCode()
);
- session.unprocessedMessageReceived(msg);
+ session.unprocessedMessageReceived(channelId, msg);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
index ee4cf14d58..2b6745ebe4 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
@@ -26,14 +26,12 @@ import org.apache.qpid.AMQInvalidRoutingKeyException;
import org.apache.qpid.client.AMQNoConsumersException;
import org.apache.qpid.client.AMQNoRouteException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ChannelCloseBody;
import org.apache.qpid.framing.ChannelCloseOkBody;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,12 +47,10 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener<Chann
return _handler;
}
- public void methodReceived(AMQStateManager stateManager, ChannelCloseBody method, int channelId)
+ public void methodReceived(AMQProtocolSession session, ChannelCloseBody method, int channelId)
throws AMQException
{
_logger.debug("ChannelClose method received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
-
AMQConstant errorCode = AMQConstant.getConstant(method.getReplyCode());
AMQShortString reason = method.getReplyText();
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java
index 8d3277d4de..9a9a0b4e63 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java
@@ -23,9 +23,7 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.ChannelCloseOkBody;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,12 +39,11 @@ public class ChannelCloseOkMethodHandler implements StateAwareMethodListener<Cha
return _instance;
}
- public void methodReceived(AMQStateManager stateManager, ChannelCloseOkBody method, int channelId)
+ public void methodReceived(AMQProtocolSession session, ChannelCloseOkBody method, int channelId)
throws AMQException
{
_logger.info("Received channel-close-ok for channel-id " + channelId);
- final AMQProtocolSession session = stateManager.getProtocolSession();
// todo this should do the local closure
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
index b47fe751d6..2153b9cc8c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowMethodHandler.java
@@ -2,7 +2,6 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.framing.ChannelFlowBody;
import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.AMQException;
import org.slf4j.Logger;
@@ -42,11 +41,9 @@ public class ChannelFlowMethodHandler implements StateAwareMethodListener<Channe
private ChannelFlowMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ChannelFlowBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ChannelFlowBody body, int channelId)
throws AMQException
{
-
- final AMQProtocolSession session = stateManager.getProtocolSession();
session.setFlowControl(channelId, body.getActive());
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java
index 96de8af54b..6f66a972d5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java
@@ -22,10 +22,8 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.ChannelFlowOkBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,7 +41,7 @@ public class ChannelFlowOkMethodHandler implements StateAwareMethodListener<Chan
private ChannelFlowOkMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ChannelFlowOkBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ChannelFlowOkBody body, int channelId)
throws AMQException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
index afb7517a12..9c791730ca 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
@@ -27,31 +27,32 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.AMQMethodNotImplementedException;
-
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class ClientMethodDispatcherImpl implements MethodDispatcher
{
-
- private static final BasicCancelOkMethodHandler _basicCancelOkMethodHandler = BasicCancelOkMethodHandler.getInstance();
- private static final BasicDeliverMethodHandler _basicDeliverMethodHandler = BasicDeliverMethodHandler.getInstance();
- private static final BasicReturnMethodHandler _basicReturnMethodHandler = BasicReturnMethodHandler.getInstance();
- private static final ChannelCloseMethodHandler _channelCloseMethodHandler = ChannelCloseMethodHandler.getInstance();
- private static final ChannelFlowOkMethodHandler _channelFlowOkMethodHandler = ChannelFlowOkMethodHandler.getInstance();
- private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
- private static final ConnectionOpenOkMethodHandler _connectionOpenOkMethodHandler = ConnectionOpenOkMethodHandler.getInstance();
+ private static final BasicCancelOkMethodHandler _basicCancelOkMethodHandler = BasicCancelOkMethodHandler.getInstance();
+ private static final BasicDeliverMethodHandler _basicDeliverMethodHandler = BasicDeliverMethodHandler.getInstance();
+ private static final BasicReturnMethodHandler _basicReturnMethodHandler = BasicReturnMethodHandler.getInstance();
+ private static final ChannelCloseMethodHandler _channelCloseMethodHandler = ChannelCloseMethodHandler.getInstance();
+ private static final ChannelFlowOkMethodHandler _channelFlowOkMethodHandler = ChannelFlowOkMethodHandler.getInstance();
+ private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
+ private static final ConnectionOpenOkMethodHandler _connectionOpenOkMethodHandler = ConnectionOpenOkMethodHandler.getInstance();
private static final ConnectionRedirectMethodHandler _connectionRedirectMethodHandler = ConnectionRedirectMethodHandler.getInstance();
- private static final ConnectionSecureMethodHandler _connectionSecureMethodHandler = ConnectionSecureMethodHandler.getInstance();
- private static final ConnectionStartMethodHandler _connectionStartMethodHandler = ConnectionStartMethodHandler.getInstance();
- private static final ConnectionTuneMethodHandler _connectionTuneMethodHandler = ConnectionTuneMethodHandler.getInstance();
- private static final ExchangeBoundOkMethodHandler _exchangeBoundOkMethodHandler = ExchangeBoundOkMethodHandler.getInstance();
- private static final QueueDeleteOkMethodHandler _queueDeleteOkMethodHandler = QueueDeleteOkMethodHandler.getInstance();
-
+ private static final ConnectionSecureMethodHandler _connectionSecureMethodHandler = ConnectionSecureMethodHandler.getInstance();
+ private static final ConnectionStartMethodHandler _connectionStartMethodHandler = ConnectionStartMethodHandler.getInstance();
+ private static final ConnectionTuneMethodHandler _connectionTuneMethodHandler = ConnectionTuneMethodHandler.getInstance();
+ private static final ExchangeBoundOkMethodHandler _exchangeBoundOkMethodHandler = ExchangeBoundOkMethodHandler.getInstance();
+ private static final QueueDeleteOkMethodHandler _queueDeleteOkMethodHandler = QueueDeleteOkMethodHandler.getInstance();
+ private static final Logger _logger = LoggerFactory.getLogger(ClientMethodDispatcherImpl.class);
private static interface DispatcherFactory
{
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager);
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQProtocolSession session);
}
private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
@@ -62,44 +63,44 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
_dispatcherFactories.put(ProtocolVersion.v8_0,
new DispatcherFactory()
{
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQProtocolSession session)
{
- return new ClientMethodDispatcherImpl_8_0(stateManager);
+ return new ClientMethodDispatcherImpl_8_0(session);
}
});
_dispatcherFactories.put(ProtocolVersion.v0_9,
new DispatcherFactory()
{
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQProtocolSession session)
{
- return new ClientMethodDispatcherImpl_0_9(stateManager);
+ return new ClientMethodDispatcherImpl_0_9(session);
}
});
}
-
- public static ClientMethodDispatcherImpl newMethodDispatcher(ProtocolVersion version, AMQStateManager stateManager)
+ public static ClientMethodDispatcherImpl newMethodDispatcher(ProtocolVersion version, AMQProtocolSession session)
{
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("New Method Dispatcher:" + session);
+ }
+
DispatcherFactory factory = _dispatcherFactories.get(version);
- return factory.createMethodDispatcher(stateManager);
+ return factory.createMethodDispatcher(session);
}
-
+ AMQProtocolSession _session;
-
- private AMQStateManager _stateManager;
-
- public ClientMethodDispatcherImpl(AMQStateManager stateManager)
+ public ClientMethodDispatcherImpl(AMQProtocolSession session)
{
- _stateManager = stateManager;
+ _session = session;
}
-
public AMQStateManager getStateManager()
{
- return _stateManager;
+ return _session.getStateManager();
}
public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
@@ -109,7 +110,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
{
- _basicCancelOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ _basicCancelOkMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -120,7 +121,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
{
- _basicDeliverMethodHandler.methodReceived(_stateManager,body,channelId);
+ _basicDeliverMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -141,13 +142,13 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
{
- _basicReturnMethodHandler.methodReceived(_stateManager,body,channelId);
+ _basicReturnMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
{
- _channelCloseMethodHandler.methodReceived(_stateManager,body,channelId);
+ _channelCloseMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -163,7 +164,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
{
- _channelFlowOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ _channelFlowOkMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -174,7 +175,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
{
- _connectionCloseMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionCloseMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -185,37 +186,37 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
{
- _connectionOpenOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionOpenOkMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
{
- _connectionRedirectMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionRedirectMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
{
- _connectionSecureMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionSecureMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
{
- _connectionStartMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionStartMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
{
- _connectionTuneMethodHandler.methodReceived(_stateManager,body,channelId);
+ _connectionTuneMethodHandler.methodReceived(_session, body, channelId);
return true;
}
public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
{
- _queueDeleteOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ _queueDeleteOkMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -431,7 +432,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
{
- _exchangeBoundOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ _exchangeBoundOkMethodHandler.methodReceived(_session, body, channelId);
return true;
}
@@ -522,7 +523,7 @@ public class ClientMethodDispatcherImpl implements MethodDispatcher
public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
{
- return false;
+ return false;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
index e235368357..d3e9fba8ed 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
@@ -26,16 +26,15 @@ import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.AMQMethodNotImplementedException;
-
+import org.apache.qpid.client.protocol.AMQProtocolSession;
public class ClientMethodDispatcherImpl_0_9 extends ClientMethodDispatcherImpl implements MethodDispatcher_0_9
{
- public ClientMethodDispatcherImpl_0_9(AMQStateManager stateManager)
+ public ClientMethodDispatcherImpl_0_9(AMQProtocolSession session)
{
- super(stateManager);
+ super(session);
}
-
public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
{
return false;
@@ -148,8 +147,7 @@ public class ClientMethodDispatcherImpl_0_9 extends ClientMethodDispatcherImpl i
public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
{
- return false;
+ return false;
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
index b0f003cd2d..19f758817d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
@@ -24,13 +24,13 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
public class ClientMethodDispatcherImpl_8_0 extends ClientMethodDispatcherImpl implements MethodDispatcher_8_0
{
- public ClientMethodDispatcherImpl_8_0(AMQStateManager stateManager)
+ public ClientMethodDispatcherImpl_8_0(AMQProtocolSession session)
{
- super(stateManager);
+ super(session);
}
public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
index 950a3288fc..bc82d6bc62 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
@@ -25,13 +25,11 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQAuthenticationException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ConnectionCloseBody;
import org.apache.qpid.framing.ConnectionCloseOkBody;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,14 +46,13 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co
}
private ConnectionCloseMethodHandler()
- { }
+ {
+ }
- public void methodReceived(AMQStateManager stateManager, ConnectionCloseBody method, int channelId)
- throws AMQException
+ public void methodReceived(AMQProtocolSession session, ConnectionCloseBody method, int channelId)
+ throws AMQException
{
_logger.info("ConnectionClose frame received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
-
// does it matter
// stateManager.changeState(AMQState.CONNECTION_CLOSING);
@@ -63,6 +60,8 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co
AMQConstant errorCode = AMQConstant.getConstant(method.getReplyCode());
AMQShortString reason = method.getReplyText();
+ AMQException error = null;
+
try
{
@@ -75,35 +74,33 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co
{
if (errorCode == AMQConstant.NOT_ALLOWED || (errorCode == AMQConstant.ACCESS_REFUSED))
{
- _logger.info("Error :" + errorCode +":"+ Thread.currentThread().getName());
-
- // todo ritchiem : Why do this here when it is going to be done in the finally block?
- session.closeProtocolSession();
+ _logger.info("Error :" + errorCode + ":" + Thread.currentThread().getName());
- // todo this is a bit of a fudge (could be conssidered such as each new connection needs a new state manager or at least a fresh state.
- stateManager.changeState(AMQState.CONNECTION_NOT_STARTED);
-
- throw new AMQAuthenticationException(errorCode, reason == null ? null : reason.toString(), null);
+ error = new AMQAuthenticationException(errorCode, reason == null ? null : reason.toString(), null);
}
else
{
_logger.info("Connection close received with error code " + errorCode);
- throw new AMQConnectionClosedException(errorCode, "Error: " + reason, null);
+ error = new AMQConnectionClosedException(errorCode, "Error: " + reason, null);
}
}
}
finally
{
- // this actually closes the connection in the case where it is not an error.
+ if (error != null)
+ {
+ session.notifyError(error);
+ }
+
+ // Close the protocol Session, including any open TCP connections
session.closeProtocolSession();
- // ritchiem: Doing this though will cause any waiting connection start to be released without being able to
- // see what the cause was.
- stateManager.changeState(AMQState.CONNECTION_CLOSED);
+ // Closing the session should not introduce a race condition as this thread will continue to propgate any
+ // exception in to the exceptionCaught method of the SessionHandler.
+ // Any sessionClosed event should occur after this.
}
}
-
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionOpenOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionOpenOkMethodHandler.java
index fd7acac84f..e639a33450 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionOpenOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionOpenOkMethodHandler.java
@@ -24,9 +24,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.ConnectionOpenOkBody;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.protocol.AMQMethodEvent;
public class ConnectionOpenOkMethodHandler implements StateAwareMethodListener<ConnectionOpenOkBody>
{
@@ -41,10 +39,10 @@ public class ConnectionOpenOkMethodHandler implements StateAwareMethodListener<C
{
}
- public void methodReceived(AMQStateManager stateManager, ConnectionOpenOkBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ConnectionOpenOkBody body, int channelId)
throws AMQException
{
- stateManager.changeState(AMQState.CONNECTION_OPEN);
+ session.getStateManager().changeState(AMQState.CONNECTION_OPEN);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
index cac68c9467..472c471fd6 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
@@ -22,10 +22,8 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.ConnectionRedirectBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,11 +44,10 @@ public class ConnectionRedirectMethodHandler implements StateAwareMethodListener
private ConnectionRedirectMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ConnectionRedirectBody method, int channelId)
+ public void methodReceived(AMQProtocolSession session, ConnectionRedirectBody method, int channelId)
throws AMQException
{
_logger.info("ConnectionRedirect frame received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
String host = method.getHost().toString();
// the host is in the form hostname:port with the port being optional
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionSecureMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionSecureMethodHandler.java
index 900aa2abac..9a9bee757b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionSecureMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionSecureMethodHandler.java
@@ -25,12 +25,9 @@ import javax.security.sasl.SaslException;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.ConnectionSecureBody;
import org.apache.qpid.framing.ConnectionSecureOkBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
public class ConnectionSecureMethodHandler implements StateAwareMethodListener<ConnectionSecureBody>
{
@@ -41,10 +38,9 @@ public class ConnectionSecureMethodHandler implements StateAwareMethodListener<C
return _instance;
}
- public void methodReceived(AMQStateManager stateManager, ConnectionSecureBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ConnectionSecureBody body, int channelId)
throws AMQException
{
- final AMQProtocolSession session = stateManager.getProtocolSession();
SaslClient client = session.getSaslClient();
if (client == null)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index d3746f137e..8857f1115a 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -25,7 +25,6 @@ import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.security.AMQCallbackHandler;
import org.apache.qpid.client.security.CallbackHandlerRegistry;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.common.ClientProperties;
import org.apache.qpid.common.QpidProperties;
@@ -35,7 +34,6 @@ import org.apache.qpid.framing.ConnectionStartOkBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,15 +60,12 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener<Co
private ConnectionStartMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ConnectionStartBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ConnectionStartBody body, int channelId)
throws AMQException
{
_log.debug("public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, "
+ "AMQMethodEvent evt): called");
- final AMQProtocolSession session = stateManager.getProtocolSession();
-
-
ProtocolVersion pv = new ProtocolVersion((byte) body.getVersionMajor(), (byte) body.getVersionMinor());
// For the purposes of interop, we can make the client accept the broker's version string.
@@ -145,7 +140,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener<Co
throw new AMQException(null, "No locales sent from server, passed: " + locales, null);
}
- stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
+ session.getStateManager().changeState(AMQState.CONNECTION_NOT_TUNED);
FieldTable clientProperties = FieldTableFactory.newFieldTable();
clientProperties.setString(new AMQShortString(ClientProperties.instance.toString()),
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
index fc0e40b745..e4e58c317d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java
@@ -24,10 +24,8 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.client.ConnectionTuneParameters;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.client.state.AMQState;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.*;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,11 +44,10 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener<Con
protected ConnectionTuneMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ConnectionTuneBody frame, int channelId)
+ public void methodReceived(AMQProtocolSession session, ConnectionTuneBody frame, int channelId)
throws AMQException
{
_logger.debug("ConnectionTune frame received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
final MethodRegistry methodRegistry = session.getMethodRegistry();
@@ -65,7 +62,7 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener<Con
params.setHeartbeat(Integer.getInteger("amqj.heartbeat.delay", frame.getHeartbeat()));
session.setConnectionTuneParameters(params);
- stateManager.changeState(AMQState.CONNECTION_NOT_OPENED);
+ session.getStateManager().changeState(AMQState.CONNECTION_NOT_OPENED);
ConnectionTuneOkBody tuneOkBody = methodRegistry.createConnectionTuneOkBody(params.getChannelMax(),
params.getFrameMax(),
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java
index 8de40beb10..690d782b40 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java
@@ -22,10 +22,8 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.ExchangeBoundOkBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +44,7 @@ public class ExchangeBoundOkMethodHandler implements StateAwareMethodListener<Ex
private ExchangeBoundOkMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, ExchangeBoundOkBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, ExchangeBoundOkBody body, int channelId)
throws AMQException
{
if (_logger.isDebugEnabled())
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java
index 41225c0569..01d82c9b55 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java
@@ -22,10 +22,8 @@ package org.apache.qpid.client.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.QueueDeleteOkBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,7 +44,7 @@ public class QueueDeleteOkMethodHandler implements StateAwareMethodListener<Queu
private QueueDeleteOkMethodHandler()
{ }
- public void methodReceived(AMQStateManager stateManager, QueueDeleteOkBody body, int channelId)
+ public void methodReceived(AMQProtocolSession session, QueueDeleteOkBody body, int channelId)
throws AMQException
{
if (_logger.isDebugEnabled())
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessage.java
deleted file mode 100644
index 8741a1cbb6..0000000000
--- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessage.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.message;
-
-import javax.jms.JMSException;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.framing.ContentHeaderProperties;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-import java.math.BigDecimal;
-
-public class AMQMessage
-{
- protected ContentHeaderProperties _contentHeaderProperties;
-
- /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
- protected AMQSession _session;
-
- protected final long _deliveryTag;
-
- public AMQMessage(ContentHeaderProperties properties, long deliveryTag)
- {
- _contentHeaderProperties = properties;
- _deliveryTag = deliveryTag;
- }
-
- public AMQMessage(ContentHeaderProperties properties)
- {
- this(properties, -1);
- }
-
- /**
- * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
- * acknowledge()
- *
- * @param s the AMQ session that delivered this message
- */
- public void setAMQSession(AMQSession s)
- {
- _session = s;
- }
-
- public AMQSession getAMQSession()
- {
- return _session;
- }
-
- /**
- * Get the AMQ message number assigned to this message
- *
- * @return the message number
- */
- public long getDeliveryTag()
- {
- return _deliveryTag;
- }
-
- /** Invoked prior to sending the message. Allows the message to be modified if necessary before sending. */
- public void prepareForSending() throws JMSException
- {
- }
-
- public FieldTable getPropertyHeaders()
- {
- return ((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders();
- }
-
- public void setDecimalProperty(AMQShortString propertyName, BigDecimal bd) throws JMSException
- {
- getPropertyHeaders().setDecimal(propertyName, bd);
- }
-
- public void setIntProperty(AMQShortString propertyName, int i) throws JMSException
- {
- getPropertyHeaders().setInteger(propertyName, new Integer(i));
- }
-
- public void setLongStringProperty(AMQShortString propertyName, String value)
- {
- getPropertyHeaders().setString(propertyName, value);
- }
-
- public void setTimestampProperty(AMQShortString propertyName, long value)
- {
- getPropertyHeaders().setTimestamp(propertyName, value);
- }
-
- public void setVoidProperty(AMQShortString propertyName)
- {
- getPropertyHeaders().setVoid(propertyName);
- }
-
- //** Getters
-
- public BigDecimal getDecimalProperty(AMQShortString propertyName) throws JMSException
- {
- return getPropertyHeaders().getDecimal(propertyName);
- }
-
- public int getIntegerProperty(AMQShortString propertyName) throws JMSException
- {
- return getPropertyHeaders().getInteger(propertyName);
- }
-
- public String getLongStringProperty(AMQShortString propertyName)
- {
- return getPropertyHeaders().getString(propertyName);
- }
-
- public Long getTimestampProperty(AMQShortString propertyName)
- {
- return getPropertyHeaders().getTimestamp(propertyName);
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java
new file mode 100644
index 0000000000..7f43e4b4b2
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate.java
@@ -0,0 +1,138 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.client.message;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import java.util.Enumeration;
+import java.util.UUID;
+
+public interface AMQMessageDelegate
+{
+ void acknowledgeThis() throws JMSException;
+
+ String getJMSMessageID() throws JMSException;
+
+ void setJMSMessageID(String string) throws JMSException;
+
+ long getJMSTimestamp() throws JMSException;
+
+ void setJMSTimestamp(long l) throws JMSException;
+
+ byte[] getJMSCorrelationIDAsBytes() throws JMSException;
+
+ void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException;
+
+ void setJMSCorrelationID(String string) throws JMSException;
+
+ String getJMSCorrelationID() throws JMSException;
+
+ Destination getJMSReplyTo() throws JMSException;
+
+ void setJMSReplyTo(Destination destination) throws JMSException;
+
+ Destination getJMSDestination() throws JMSException;
+
+ int getJMSDeliveryMode() throws JMSException;
+
+ void setJMSDeliveryMode(int i) throws JMSException;
+
+ String getJMSType() throws JMSException;
+
+ void setJMSType(String string) throws JMSException;
+
+ long getJMSExpiration() throws JMSException;
+
+ void setJMSExpiration(long l) throws JMSException;
+
+ int getJMSPriority() throws JMSException;
+
+ void setJMSPriority(int i) throws JMSException;
+
+ void clearProperties() throws JMSException;
+
+ boolean propertyExists(String string) throws JMSException;
+
+ boolean getBooleanProperty(String string) throws JMSException;
+
+ byte getByteProperty(String string) throws JMSException;
+
+ short getShortProperty(String string) throws JMSException;
+
+ int getIntProperty(String string) throws JMSException;
+
+ long getLongProperty(String string) throws JMSException;
+
+ float getFloatProperty(String string) throws JMSException;
+
+ double getDoubleProperty(String string) throws JMSException;
+
+ String getStringProperty(String string) throws JMSException;
+
+ Object getObjectProperty(String string) throws JMSException;
+
+ Enumeration getPropertyNames() throws JMSException;
+
+ void setBooleanProperty(String string, boolean b) throws JMSException;
+
+ void setByteProperty(String string, byte b) throws JMSException;
+
+ void setShortProperty(String string, short i) throws JMSException;
+
+ void setIntProperty(String string, int i) throws JMSException;
+
+ void setLongProperty(String string, long l) throws JMSException;
+
+ void setFloatProperty(String string, float v) throws JMSException;
+
+ void setDoubleProperty(String string, double v) throws JMSException;
+
+ void setStringProperty(String string, String string1) throws JMSException;
+
+ void setObjectProperty(String string, Object object) throws JMSException;
+
+ void acknowledge() throws JMSException;
+
+ public void setJMSDestination(Destination destination);
+
+ public void setContentType(String contentType);
+ public String getContentType();
+
+ public void setEncoding(String encoding);
+ public String getEncoding();
+
+
+ String getReplyToString();
+
+ void removeProperty(final String propertyName) throws JMSException;
+
+ void setAMQSession(final AMQSession s);
+
+ AMQSession getAMQSession();
+
+ long getDeliveryTag();
+
+ void setJMSMessageID(final UUID messageId) throws JMSException;
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java
new file mode 100644
index 0000000000..8c3f2fd08f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegateFactory.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.client.message;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.AMQException;
+
+public interface AMQMessageDelegateFactory<D extends AMQMessageDelegate>
+{
+ public static AMQMessageDelegateFactory DEFAULT_FACTORY = null;
+
+ public static AMQMessageDelegateFactory<AMQMessageDelegate_0_8> FACTORY_0_8 =
+ new AMQMessageDelegateFactory<AMQMessageDelegate_0_8>()
+ {
+ public AMQMessageDelegate_0_8 createDelegate()
+ {
+ return new AMQMessageDelegate_0_8();
+ }
+ };
+
+ public static AMQMessageDelegateFactory<AMQMessageDelegate_0_10> FACTORY_0_10 =
+ new AMQMessageDelegateFactory<AMQMessageDelegate_0_10>()
+ {
+ public AMQMessageDelegate_0_10 createDelegate()
+ {
+ return new AMQMessageDelegate_0_10();
+ }
+ };
+
+
+ public D createDelegate();
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java
new file mode 100644
index 0000000000..8b4488f1f9
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java
@@ -0,0 +1,973 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.client.message;
+
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.qpid.client.*;
+import org.apache.qpid.framing.ContentHeaderProperties;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQPInvalidClassException;
+import org.apache.qpid.nclient.*;
+import org.apache.qpid.jms.Message;
+import org.apache.qpid.url.BindingURL;
+import org.apache.qpid.url.AMQBindingURL;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.transport.*;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageNotWriteableException;
+import javax.jms.MessageFormatException;
+import javax.jms.DeliveryMode;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import org.apache.qpid.exchange.ExchangeDefaults;
+
+public class AMQMessageDelegate_0_10 implements AMQMessageDelegate
+{
+ private static final Map<ReplyTo, Destination> _destinationCache = Collections.synchronizedMap(new ReferenceMap());
+
+ public static final String JMS_TYPE = "x-jms-type";
+
+
+ private boolean _readableProperties = false;
+
+ private Destination _destination;
+
+
+ private MessageProperties _messageProps;
+ private DeliveryProperties _deliveryProps;
+ /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
+ private AMQSession _session;
+ private final long _deliveryTag;
+
+ private static Map<AMQShortString,Integer> _exchangeTypeMap = new ConcurrentHashMap<AMQShortString, Integer>();
+ private static Map<String,Integer> _exchangeTypeStringMap = new ConcurrentHashMap<String, Integer>();
+ private static Map<String, Integer> _exchangeTypeToDestinationType = new ConcurrentHashMap<String, Integer>();;
+
+ static
+ {
+ _exchangeTypeMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME, AMQDestination.QUEUE_TYPE);
+ _exchangeTypeMap.put(AMQShortString.EMPTY_STRING, AMQDestination.QUEUE_TYPE);
+ _exchangeTypeMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME, AMQDestination.TOPIC_TYPE);
+ _exchangeTypeMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME, AMQDestination.TOPIC_TYPE);
+
+ _exchangeTypeStringMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME.toString(), AMQDestination.QUEUE_TYPE);
+ _exchangeTypeStringMap.put("", AMQDestination.QUEUE_TYPE);
+ _exchangeTypeStringMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
+ _exchangeTypeStringMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
+
+
+ _exchangeTypeToDestinationType.put(ExchangeDefaults.DIRECT_EXCHANGE_CLASS.toString(), AMQDestination.QUEUE_TYPE);
+ _exchangeTypeToDestinationType.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
+ _exchangeTypeToDestinationType.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), AMQDestination.TOPIC_TYPE);
+ }
+
+ protected AMQMessageDelegate_0_10()
+ {
+ this(new MessageProperties(), new DeliveryProperties(), -1);
+ _readableProperties = false;
+ }
+
+ protected AMQMessageDelegate_0_10(long deliveryTag, MessageProperties messageProps, DeliveryProperties deliveryProps, AMQShortString exchange,
+ AMQShortString routingKey) throws AMQException
+ {
+ this(messageProps, deliveryProps, deliveryTag);
+
+
+ AMQDestination dest;
+
+ dest = generateDestination(exchange, routingKey);
+ setJMSDestination(dest);
+ }
+
+ private AMQDestination generateDestination(AMQShortString exchange, AMQShortString routingKey)
+ {
+ AMQDestination dest;
+ switch(getExchangeType(exchange))
+ {
+ case AMQDestination.QUEUE_TYPE:
+ dest = new AMQQueue(exchange, routingKey, routingKey);
+ break;
+ case AMQDestination.TOPIC_TYPE:
+ dest = new AMQTopic(exchange, routingKey, null);
+ break;
+ default:
+ dest = new AMQUndefinedDestination(exchange, routingKey, null);
+
+ }
+
+ return dest;
+ }
+
+ private int getExchangeType(AMQShortString exchange)
+ {
+ Integer type = _exchangeTypeMap.get(exchange == null ? AMQShortString.EMPTY_STRING : exchange);
+
+ if(type == null)
+ {
+ return AMQDestination.UNKNOWN_TYPE;
+ }
+
+
+ return type;
+ }
+
+
+ public static void updateExchangeTypeMapping(Header header, org.apache.qpid.nclient.Session session)
+ {
+ DeliveryProperties deliveryProps = header.get(DeliveryProperties.class);
+ if(deliveryProps != null)
+ {
+ String exchange = deliveryProps.getExchange();
+
+ if(exchange != null && !_exchangeTypeStringMap.containsKey(exchange))
+ {
+
+ AMQShortString exchangeShortString = new AMQShortString(exchange);
+ Future<ExchangeQueryResult> future =
+ session.exchangeQuery(exchange.toString());
+ ExchangeQueryResult res = future.get();
+
+ Integer type = _exchangeTypeToDestinationType.get(res.getType());
+ if(type == null)
+ {
+ type = AMQDestination.UNKNOWN_TYPE;
+ }
+ _exchangeTypeStringMap.put(exchange, type);
+ _exchangeTypeMap.put(exchangeShortString, type);
+
+ }
+ }
+ }
+
+ protected AMQMessageDelegate_0_10(MessageProperties messageProps, DeliveryProperties deliveryProps, long deliveryTag)
+ {
+ _messageProps = messageProps;
+ _deliveryProps = deliveryProps;
+ _deliveryTag = deliveryTag;
+ _readableProperties = (_messageProps != null);
+
+ }
+
+
+ public String getJMSMessageID() throws JMSException
+ {
+ UUID id = _messageProps.getMessageId();
+ return id == null ? null : "ID:" + id;
+ }
+
+ public void setJMSMessageID(String messageId) throws JMSException
+ {
+ if(messageId == null)
+ {
+ _messageProps.clearMessageId();
+ }
+ else
+ {
+ if(messageId.startsWith("ID:"))
+ {
+ try
+ {
+ _messageProps.setMessageId(UUID.fromString(messageId.substring(3)));
+ }
+ catch(IllegalArgumentException ex)
+ {
+ throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID");
+ }
+ }
+ else
+ {
+ throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID");
+ }
+ }
+ }
+
+ public void setJMSMessageID(UUID messageId) throws JMSException
+ {
+ if(messageId == null)
+ {
+ _messageProps.clearMessageId();
+ }
+ else
+ {
+ _messageProps.setMessageId(messageId);
+ }
+ }
+
+
+ public long getJMSTimestamp() throws JMSException
+ {
+ return _deliveryProps.getTimestamp();
+ }
+
+ public void setJMSTimestamp(long timestamp) throws JMSException
+ {
+ _deliveryProps.setTimestamp(timestamp);
+ }
+
+ public byte[] getJMSCorrelationIDAsBytes() throws JMSException
+ {
+ return _messageProps.getCorrelationId();
+ }
+
+ public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
+ {
+ _messageProps.setCorrelationId(bytes);
+ }
+
+ public void setJMSCorrelationID(String correlationId) throws JMSException
+ {
+
+ setJMSCorrelationIDAsBytes(correlationId == null ? null : correlationId.getBytes());
+ }
+
+ public String getJMSCorrelationID() throws JMSException
+ {
+
+ byte[] correlationIDAsBytes = getJMSCorrelationIDAsBytes();
+ return correlationIDAsBytes == null ? null : new String(correlationIDAsBytes);
+ }
+
+ public Destination getJMSReplyTo()
+ {
+ ReplyTo replyTo = _messageProps.getReplyTo();
+
+ if (replyTo == null)
+ {
+ return null;
+ }
+ else
+ {
+ Destination dest = _destinationCache.get(replyTo);
+ if (dest == null)
+ {
+ String exchange = replyTo.getExchange();
+ String routingKey = replyTo.getRoutingKey();
+
+ dest = generateDestination(exchange == null ? null : new AMQShortString(exchange),
+ routingKey == null ? null : new AMQShortString(routingKey));
+
+
+
+
+
+ _destinationCache.put(replyTo, dest);
+ }
+
+ return dest;
+ }
+ }
+
+ public void setJMSReplyTo(Destination destination) throws JMSException
+ {
+ if (destination == null)
+ {
+ throw new IllegalArgumentException("Null destination not allowed");
+ }
+
+ if (!(destination instanceof AMQDestination))
+ {
+ throw new IllegalArgumentException(
+ "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass());
+ }
+
+ final AMQDestination amqd = (AMQDestination) destination;
+
+ final ReplyTo replyTo = new ReplyTo(amqd.getExchangeName().toString(), amqd.getRoutingKey().toString());
+ _destinationCache.put(replyTo, destination);
+ _messageProps.setReplyTo(replyTo);
+
+ }
+
+ public Destination getJMSDestination() throws JMSException
+ {
+ return _destination;
+ }
+
+ public void setJMSDestination(Destination destination)
+ {
+ _destination = destination;
+ }
+
+ public void setContentType(String contentType)
+ {
+ _messageProps.setContentType(contentType);
+ }
+
+ public String getContentType()
+ {
+ return _messageProps.getContentType();
+ }
+
+ public void setEncoding(String encoding)
+ {
+ if(encoding == null || encoding.length() == 0)
+ {
+ _messageProps.clearContentEncoding();
+ }
+ else
+ {
+ _messageProps.setContentEncoding(encoding);
+ }
+ }
+
+ public String getEncoding()
+ {
+ return _messageProps.getContentEncoding();
+ }
+
+ public String getReplyToString()
+ {
+ Destination replyTo = getJMSReplyTo();
+ if(replyTo != null)
+ {
+ return ((AMQDestination)replyTo).toURL();
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+
+ public int getJMSDeliveryMode() throws JMSException
+ {
+
+ MessageDeliveryMode deliveryMode = _deliveryProps.getDeliveryMode();
+ if(deliveryMode != null)
+ {
+ switch(deliveryMode)
+ {
+ case PERSISTENT :
+ return DeliveryMode.PERSISTENT;
+ case NON_PERSISTENT:
+ return DeliveryMode.NON_PERSISTENT;
+ default:
+ throw new JMSException("Unknown Message Delivery Mode: " + _deliveryProps.getDeliveryMode());
+ }
+ }
+ else
+ {
+ return Message.DEFAULT_DELIVERY_MODE;
+ }
+
+ }
+
+ public void setJMSDeliveryMode(int deliveryMode) throws JMSException
+ {
+ switch(deliveryMode)
+ {
+ case DeliveryMode.PERSISTENT:
+ _deliveryProps.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
+ break;
+ case DeliveryMode.NON_PERSISTENT:
+ _deliveryProps.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
+ break;
+ default:
+ throw new JMSException("Unknown JMS Delivery Mode: " + deliveryMode);
+ }
+
+ }
+
+
+ public String getJMSType() throws JMSException
+ {
+ if(getApplicationHeaders().containsKey(JMS_TYPE))
+ {
+ return getStringProperty(JMS_TYPE);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private Map<String, Object> getApplicationHeaders()
+ {
+ Map<String, Object> map = _messageProps.getApplicationHeaders();
+ return map == null ? Collections.EMPTY_MAP : map;
+ }
+
+ public void setJMSType(String type) throws JMSException
+ {
+ Map<String, Object> headers = _messageProps.getApplicationHeaders();
+ if(type == null)
+ {
+ if(headers != null)
+ {
+ headers.remove(JMS_TYPE);
+ }
+ }
+ else
+ {
+ if(headers == null)
+ {
+ headers = new HashMap<String,Object>();
+ _messageProps.setApplicationHeaders(headers);
+
+ }
+ headers.put(JMS_TYPE, type);
+ }
+ }
+
+ public long getJMSExpiration() throws JMSException
+ {
+ return _deliveryProps.getExpiration();
+ }
+
+ public void setJMSExpiration(long l) throws JMSException
+ {
+ _deliveryProps.setExpiration(l);
+ }
+
+
+
+ public boolean propertyExists(String propertyName) throws JMSException
+ {
+ return getApplicationHeaders().containsKey(propertyName);
+ }
+
+ public boolean getBooleanProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Object o = getApplicationHeaders().get(propertyName);
+
+ if(o instanceof Boolean)
+ {
+ return ((Boolean)o).booleanValue();
+ }
+ else if(o instanceof String)
+ {
+ return Boolean.valueOf((String) o).booleanValue();
+ }
+ else if(getApplicationHeaders().containsKey(propertyName))
+ {
+ throw new MessageFormatException("getBooleanProperty(\""+propertyName+"\") failed as value is not boolean: " + o);
+ }
+ else
+ {
+ return Boolean.valueOf(null);
+ }
+ }
+
+ public byte getByteProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Byte)
+ {
+ return ((Byte)o).byteValue();
+ }
+ else if(o instanceof String)
+ {
+ return Byte.valueOf((String) o).byteValue();
+ }
+ else if(getApplicationHeaders().containsKey(propertyName))
+ {
+ throw new MessageFormatException("getByteProperty(\""+propertyName+"\") failed as value is not a byte: " + o);
+ }
+ else
+ {
+ return Byte.valueOf(null);
+ }
+ }
+
+ public short getShortProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Short)
+ {
+ return ((Short)o).shortValue();
+ }
+ else
+ {
+ try
+ {
+ return Short.valueOf(getByteProperty(propertyName));
+ }
+ catch(MessageFormatException e)
+ {
+ throw new MessageFormatException("getShortProperty(\""+propertyName+"\") failed as value is not a short: " + o);
+ }
+ }
+
+
+ }
+
+ public int getIntProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Integer)
+ {
+ return ((Integer)o).intValue();
+ }
+ else
+ {
+ try
+ {
+ return Integer.valueOf(getShortProperty(propertyName));
+ }
+ catch(MessageFormatException e)
+ {
+ throw new MessageFormatException("getIntProperty(\""+propertyName+"\") failed as value is not an int: " + o);
+ }
+
+ }
+ }
+
+ public long getLongProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Long)
+ {
+ return ((Long)o).longValue();
+ }
+ else
+ {
+ try
+ {
+ return Long.valueOf(getIntProperty(propertyName));
+ }
+ catch(MessageFormatException e)
+ {
+ throw new MessageFormatException("getLongProperty(\""+propertyName+"\") failed as value is not a long: " + o);
+ }
+
+ }
+ }
+
+ public float getFloatProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Float)
+ {
+ return ((Float)o).floatValue();
+ }
+ else if(o instanceof String)
+ {
+ return Float.valueOf((String) o).floatValue();
+ }
+ else if(getApplicationHeaders().containsKey(propertyName))
+ {
+ throw new MessageFormatException("getFloatProperty(\""+propertyName+"\") failed as value is not a float: " + o);
+ }
+ else
+ {
+ return Float.valueOf(null);
+ }
+
+ }
+
+ public double getDoubleProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof Double)
+ {
+ return ((Double)o).doubleValue();
+ }
+ else
+ {
+ try
+ {
+ return Double.valueOf(getFloatProperty(propertyName));
+ }
+ catch(MessageFormatException e)
+ {
+ throw new MessageFormatException("getDoubleProperty(\""+propertyName+"\") failed as value is not a double: " + o);
+ }
+
+ }
+ }
+
+ public String getStringProperty(String propertyName) throws JMSException
+ {
+ if (propertyName.equals(CustomJMSXProperty.JMSXUserID.toString()))
+ {
+ return new String(_messageProps.getUserId());
+ }
+ else
+ {
+ checkPropertyName(propertyName);
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ Object o = propertyMap.get(propertyName);
+
+ if(o instanceof String)
+ {
+ return (String) o;
+ }
+ else if(o == null)
+ {
+ return null;
+ }
+ else if(o.getClass().isArray())
+ {
+ throw new MessageFormatException("getString(\""+propertyName+"\") failed as value of type " + o.getClass()+ " is an array.");
+ }
+ else
+ {
+ return String.valueOf(o);
+ }
+
+ }
+ }
+
+ public Object getObjectProperty(String propertyName) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ Map<String, Object> propertyMap = getApplicationHeaders();
+
+ return propertyMap.get(propertyName);
+
+ }
+
+ public Enumeration getPropertyNames() throws JMSException
+ {
+ return java.util.Collections.enumeration(getApplicationHeaders().keySet());
+ }
+
+ public void setBooleanProperty(String propertyName, boolean b) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, b);
+ }
+
+ public void setByteProperty(String propertyName, byte b) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, b);
+ }
+
+ public void setShortProperty(String propertyName, short i) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, i);
+ }
+
+ public void setIntProperty(String propertyName, int i) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, i);
+ }
+
+ public void setLongProperty(String propertyName, long l) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, l);
+ }
+
+ public void setFloatProperty(String propertyName, float f) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, f);
+ }
+
+ public void setDoubleProperty(String propertyName, double v) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, v);
+ }
+
+ public void setStringProperty(String propertyName, String value) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ setApplicationHeader(propertyName, value);
+ }
+
+ private static final Set<Class> ALLOWED = new HashSet();
+ static
+ {
+ ALLOWED.add(Boolean.class);
+ ALLOWED.add(Byte.class);
+ ALLOWED.add(Short.class);
+ ALLOWED.add(Integer.class);
+ ALLOWED.add(Long.class);
+ ALLOWED.add(Float.class);
+ ALLOWED.add(Double.class);
+ ALLOWED.add(Character.class);
+ ALLOWED.add(String.class);
+ ALLOWED.add(byte[].class);
+ }
+
+ public void setObjectProperty(String propertyName, Object object) throws JMSException
+ {
+ checkPropertyName(propertyName);
+ checkWritableProperties();
+ if (object != null && !ALLOWED.contains(object.getClass()))
+ {
+ throw new MessageFormatException
+ (String.format
+ ("Cannot set a %s, allowed property types are: %s",
+ object.getClass(), ALLOWED));
+ }
+ setApplicationHeader(propertyName, object);
+ }
+
+ private void setApplicationHeader(String propertyName, Object object)
+ {
+ Map<String, Object> headers = _messageProps.getApplicationHeaders();
+ if(headers == null)
+ {
+ headers = new HashMap<String,Object>();
+ _messageProps.setApplicationHeaders(headers);
+ }
+ headers.put(propertyName, object);
+ }
+
+ public void removeProperty(String propertyName) throws JMSException
+ {
+ Map<String, Object> headers = _messageProps.getApplicationHeaders();
+ if(headers != null)
+ {
+ headers.remove(propertyName);
+ }
+ }
+
+
+
+ protected void checkWritableProperties() throws MessageNotWriteableException
+ {
+ if (_readableProperties)
+ {
+ throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
+ }
+ }
+
+
+ public int getJMSPriority() throws JMSException
+ {
+ MessageDeliveryPriority messageDeliveryPriority = _deliveryProps.getPriority();
+ return messageDeliveryPriority == null ? Message.DEFAULT_PRIORITY : messageDeliveryPriority.getValue();
+ }
+
+ public void setJMSPriority(int i) throws JMSException
+ {
+ _deliveryProps.setPriority(MessageDeliveryPriority.get((short)i));
+ }
+
+ public void clearProperties() throws JMSException
+ {
+ if(!getApplicationHeaders().isEmpty())
+ {
+ getApplicationHeaders().clear();
+ }
+
+ _readableProperties = false;
+ }
+
+
+ public void acknowledgeThis() throws JMSException
+ {
+ // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
+ // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
+ if (_session != null)
+ {
+ if (_session.getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection is already closed");
+ }
+
+ // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
+ // received on the session
+ _session.acknowledgeMessage(_deliveryTag, true);
+ }
+ }
+
+ public void acknowledge() throws JMSException
+ {
+ if (_session != null)
+ {
+ _session.acknowledge();
+ }
+ }
+
+
+ /**
+ * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
+ * acknowledge()
+ *
+ * @param s the AMQ session that delivered this message
+ */
+ public void setAMQSession(AMQSession s)
+ {
+ _session = s;
+ }
+
+ public AMQSession getAMQSession()
+ {
+ return _session;
+ }
+
+ /**
+ * Get the AMQ message number assigned to this message
+ *
+ * @return the message number
+ */
+ public long getDeliveryTag()
+ {
+ return _deliveryTag;
+ }
+
+
+
+
+
+
+ protected void checkPropertyName(CharSequence propertyName)
+ {
+ if (propertyName == null)
+ {
+ throw new IllegalArgumentException("Property name must not be null");
+ }
+ else if (propertyName.length() == 0)
+ {
+ throw new IllegalArgumentException("Property name must not be the empty string");
+ }
+
+ checkIdentiferFormat(propertyName);
+ }
+
+ protected void checkIdentiferFormat(CharSequence propertyName)
+ {
+// JMS requirements 3.5.1 Property Names
+// Identifiers:
+// - An identifier is an unlimited-length character sequence that must begin
+// with a Java identifier start character; all following characters must be Java
+// identifier part characters. An identifier start character is any character for
+// which the method Character.isJavaIdentifierStart returns true. This includes
+// '_' and '$'. An identifier part character is any character for which the
+// method Character.isJavaIdentifierPart returns true.
+// - Identifiers cannot be the names NULL, TRUE, or FALSE.
+// Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
+// ESCAPE.
+// Identifiers are either header field references or property references. The
+// type of a property value in a message selector corresponds to the type
+// used to set the property. If a property that does not exist in a message is
+// referenced, its value is NULL. The semantics of evaluating NULL values
+// in a selector are described in Section 3.8.1.2, Null Values.
+// The conversions that apply to the get methods for properties do not
+// apply when a property is used in a message selector expression. For
+// example, suppose you set a property as a string value, as in the
+// following:
+// myMessage.setStringProperty("NumberOfOrders", "2");
+// The following expression in a message selector would evaluate to false,
+// because a string cannot be used in an arithmetic expression:
+// "NumberOfOrders > 1"
+// Identifiers are case sensitive.
+// Message header field references are restricted to JMSDeliveryMode,
+// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
+// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
+// null and if so are treated as a NULL value.
+
+ if (Boolean.getBoolean("strict-jms"))
+ {
+ // JMS start character
+ if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
+ }
+
+ // JMS part character
+ int length = propertyName.length();
+ for (int c = 1; c < length; c++)
+ {
+ if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
+ }
+ }
+
+ // JMS invalid names
+ if ((propertyName.equals("NULL")
+ || propertyName.equals("TRUE")
+ || propertyName.equals("FALSE")
+ || propertyName.equals("NOT")
+ || propertyName.equals("AND")
+ || propertyName.equals("OR")
+ || propertyName.equals("BETWEEN")
+ || propertyName.equals("LIKE")
+ || propertyName.equals("IN")
+ || propertyName.equals("IS")
+ || propertyName.equals("ESCAPE")))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
+ }
+ }
+
+ }
+
+
+ public MessageProperties getMessageProperties()
+ {
+ return _messageProps;
+ }
+
+
+ public DeliveryProperties getDeliveryProperties()
+ {
+ return _deliveryProps;
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java
new file mode 100644
index 0000000000..4c20a44849
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_8.java
@@ -0,0 +1,567 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.client.message;
+
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.CustomJMSXProperty;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.client.AMQUndefinedDestination;
+import org.apache.qpid.client.JMSAMQException;
+import org.apache.qpid.framing.ContentHeaderProperties;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.url.BindingURL;
+import org.apache.qpid.url.AMQBindingURL;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageNotWriteableException;
+import java.util.Map;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.UUID;
+import java.net.URISyntaxException;
+
+public class AMQMessageDelegate_0_8 implements AMQMessageDelegate
+{
+ private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap());
+
+ public static final String JMS_TYPE = "x-jms-type";
+
+
+ private boolean _readableProperties = false;
+
+ private Destination _destination;
+ private JMSHeaderAdapter _headerAdapter;
+ private static final boolean STRICT_AMQP_COMPLIANCE =
+ Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT));
+
+ private ContentHeaderProperties _contentHeaderProperties;
+ /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
+ private AMQSession _session;
+ private final long _deliveryTag;
+
+ protected AMQMessageDelegate_0_8()
+ {
+ this(new BasicContentHeaderProperties(), -1);
+ _readableProperties = false;
+ _headerAdapter = new JMSHeaderAdapter(((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders());
+
+ }
+
+ protected AMQMessageDelegate_0_8(long deliveryTag, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
+ AMQShortString routingKey)
+ {
+ this(contentHeader, deliveryTag);
+
+ Integer type = contentHeader.getHeaders().getInteger(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName());
+
+ if(type == null)
+ {
+ type = AMQDestination.UNKNOWN_TYPE;
+ }
+
+ AMQDestination dest;
+
+ switch(type.intValue())
+ {
+ case AMQDestination.QUEUE_TYPE:
+ dest = new AMQQueue(exchange, routingKey, routingKey);
+ break;
+ case AMQDestination.TOPIC_TYPE:
+ dest = new AMQTopic(exchange, routingKey, null);
+ break;
+ default:
+ dest = new AMQUndefinedDestination(exchange, routingKey, null);
+ }
+
+
+
+ // Destination dest = AMQDestination.createDestination(url);
+ setJMSDestination(dest);
+
+
+
+ }
+
+ protected AMQMessageDelegate_0_8(BasicContentHeaderProperties properties, long deliveryTag)
+ {
+ _contentHeaderProperties = properties;
+ _deliveryTag = deliveryTag;
+ _readableProperties = (_contentHeaderProperties != null);
+ _headerAdapter = new JMSHeaderAdapter(((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders());
+ }
+
+
+ public String getJMSMessageID() throws JMSException
+ {
+ return getContentHeaderProperties().getMessageIdAsString();
+ }
+
+ public void setJMSMessageID(String messageId) throws JMSException
+ {
+ getContentHeaderProperties().setMessageId(messageId);
+ }
+
+ public void setJMSMessageID(UUID messageId) throws JMSException
+ {
+ getContentHeaderProperties().setMessageId("ID:" + messageId);
+ }
+
+
+ public long getJMSTimestamp() throws JMSException
+ {
+ return getContentHeaderProperties().getTimestamp();
+ }
+
+ public void setJMSTimestamp(long timestamp) throws JMSException
+ {
+ getContentHeaderProperties().setTimestamp(timestamp);
+ }
+
+ public byte[] getJMSCorrelationIDAsBytes() throws JMSException
+ {
+ return getContentHeaderProperties().getCorrelationIdAsString().getBytes();
+ }
+
+ public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
+ {
+ getContentHeaderProperties().setCorrelationId(new String(bytes));
+ }
+
+ public void setJMSCorrelationID(String correlationId) throws JMSException
+ {
+ getContentHeaderProperties().setCorrelationId(correlationId);
+ }
+
+ public String getJMSCorrelationID() throws JMSException
+ {
+ return getContentHeaderProperties().getCorrelationIdAsString();
+ }
+
+ public Destination getJMSReplyTo() throws JMSException
+ {
+ String replyToEncoding = getContentHeaderProperties().getReplyToAsString();
+ if (replyToEncoding == null)
+ {
+ return null;
+ }
+ else
+ {
+ Destination dest = (Destination) _destinationCache.get(replyToEncoding);
+ if (dest == null)
+ {
+ try
+ {
+ BindingURL binding = new AMQBindingURL(replyToEncoding);
+ dest = AMQDestination.createDestination(binding);
+ }
+ catch (URISyntaxException e)
+ {
+ throw new JMSAMQException("Illegal value in JMS_ReplyTo property: " + replyToEncoding, e);
+ }
+
+ _destinationCache.put(replyToEncoding, dest);
+ }
+
+ return dest;
+ }
+ }
+
+ public void setJMSReplyTo(Destination destination) throws JMSException
+ {
+ if (destination == null)
+ {
+ throw new IllegalArgumentException("Null destination not allowed");
+ }
+
+ if (!(destination instanceof AMQDestination))
+ {
+ throw new IllegalArgumentException(
+ "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass());
+ }
+
+ final AMQDestination amqd = (AMQDestination) destination;
+
+ final AMQShortString encodedDestination = amqd.getEncodedName();
+ _destinationCache.put(encodedDestination, destination);
+ getContentHeaderProperties().setReplyTo(encodedDestination);
+ }
+
+ public Destination getJMSDestination() throws JMSException
+ {
+ return _destination;
+ }
+
+ public void setJMSDestination(Destination destination)
+ {
+ _destination = destination;
+ }
+
+ public void setContentType(String contentType)
+ {
+ getContentHeaderProperties().setContentType(contentType);
+ }
+
+ public String getContentType()
+ {
+ return getContentHeaderProperties().getContentTypeAsString();
+ }
+
+ public void setEncoding(String encoding)
+ {
+ getContentHeaderProperties().setEncoding(encoding);
+ }
+
+ public String getEncoding()
+ {
+ return getContentHeaderProperties().getEncodingAsString();
+ }
+
+ public String getReplyToString()
+ {
+ return getContentHeaderProperties().getReplyToAsString();
+ }
+
+ public int getJMSDeliveryMode() throws JMSException
+ {
+ return getContentHeaderProperties().getDeliveryMode();
+ }
+
+ public void setJMSDeliveryMode(int i) throws JMSException
+ {
+ getContentHeaderProperties().setDeliveryMode((byte) i);
+ }
+
+ public BasicContentHeaderProperties getContentHeaderProperties()
+ {
+ return (BasicContentHeaderProperties) _contentHeaderProperties;
+ }
+
+
+ public String getJMSType() throws JMSException
+ {
+ return getContentHeaderProperties().getTypeAsString();
+ }
+
+ public void setJMSType(String string) throws JMSException
+ {
+ getContentHeaderProperties().setType(string);
+ }
+
+ public long getJMSExpiration() throws JMSException
+ {
+ return getContentHeaderProperties().getExpiration();
+ }
+
+ public void setJMSExpiration(long l) throws JMSException
+ {
+ getContentHeaderProperties().setExpiration(l);
+ }
+
+
+
+ public boolean propertyExists(String propertyName) throws JMSException
+ {
+ return getJmsHeaders().propertyExists(propertyName);
+ }
+
+ public boolean getBooleanProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getBoolean(propertyName);
+ }
+
+ public byte getByteProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getByte(propertyName);
+ }
+
+ public short getShortProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getShort(propertyName);
+ }
+
+ public int getIntProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getInteger(propertyName);
+ }
+
+ public long getLongProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getLong(propertyName);
+ }
+
+ public float getFloatProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getFloat(propertyName);
+ }
+
+ public double getDoubleProperty(String propertyName) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getDouble(propertyName);
+ }
+
+ public String getStringProperty(String propertyName) throws JMSException
+ {
+ //NOTE: if the JMSX Property is a non AMQP property then we must check _strictAMQP and throw as below.
+ if (propertyName.equals(CustomJMSXProperty.JMSXUserID.toString()))
+ {
+ return ((BasicContentHeaderProperties) _contentHeaderProperties).getUserIdAsString();
+ }
+ else
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ return getJmsHeaders().getString(propertyName);
+ }
+ }
+
+ public Object getObjectProperty(String propertyName) throws JMSException
+ {
+ return getJmsHeaders().getObject(propertyName);
+ }
+
+ public Enumeration getPropertyNames() throws JMSException
+ {
+ return getJmsHeaders().getPropertyNames();
+ }
+
+ public void setBooleanProperty(String propertyName, boolean b) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setBoolean(propertyName, b);
+ }
+
+ public void setByteProperty(String propertyName, byte b) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setByte(propertyName, new Byte(b));
+ }
+
+ public void setShortProperty(String propertyName, short i) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setShort(propertyName, new Short(i));
+ }
+
+ public void setIntProperty(String propertyName, int i) throws JMSException
+ {
+ checkWritableProperties();
+ getJmsHeaders().setInteger(propertyName, new Integer(i));
+ }
+
+ public void setLongProperty(String propertyName, long l) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setLong(propertyName, new Long(l));
+ }
+
+ public void setFloatProperty(String propertyName, float f) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setFloat(propertyName, new Float(f));
+ }
+
+ public void setDoubleProperty(String propertyName, double v) throws JMSException
+ {
+ if (STRICT_AMQP_COMPLIANCE)
+ {
+ throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
+ }
+
+ checkWritableProperties();
+ getJmsHeaders().setDouble(propertyName, new Double(v));
+ }
+
+ public void setStringProperty(String propertyName, String value) throws JMSException
+ {
+ checkWritableProperties();
+ getJmsHeaders().setString(propertyName, value);
+ }
+
+ public void setObjectProperty(String propertyName, Object object) throws JMSException
+ {
+ checkWritableProperties();
+ getJmsHeaders().setObject(propertyName, object);
+ }
+
+ public void removeProperty(String propertyName) throws JMSException
+ {
+ getJmsHeaders().remove(propertyName);
+ }
+
+
+ private JMSHeaderAdapter getJmsHeaders()
+ {
+ return _headerAdapter;
+ }
+
+ protected void checkWritableProperties() throws MessageNotWriteableException
+ {
+ if (_readableProperties)
+ {
+ throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
+ }
+ _contentHeaderProperties.updated();
+ }
+
+
+ public int getJMSPriority() throws JMSException
+ {
+ return getContentHeaderProperties().getPriority();
+ }
+
+ public void setJMSPriority(int i) throws JMSException
+ {
+ getContentHeaderProperties().setPriority((byte) i);
+ }
+
+ public void clearProperties() throws JMSException
+ {
+ getJmsHeaders().clear();
+
+ _readableProperties = false;
+ }
+
+
+ public void acknowledgeThis() throws JMSException
+ {
+ // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
+ // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
+ if (_session != null)
+ {
+ if (_session.getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection is already closed");
+ }
+
+ // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
+ // received on the session
+ _session.acknowledgeMessage(_deliveryTag, true);
+ }
+ }
+
+ public void acknowledge() throws JMSException
+ {
+ if (_session != null)
+ {
+ _session.acknowledge();
+ }
+ }
+
+
+ /**
+ * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
+ * acknowledge()
+ *
+ * @param s the AMQ session that delivered this message
+ */
+ public void setAMQSession(AMQSession s)
+ {
+ _session = s;
+ }
+
+ public AMQSession getAMQSession()
+ {
+ return _session;
+ }
+
+ /**
+ * Get the AMQ message number assigned to this message
+ *
+ * @return the message number
+ */
+ public long getDeliveryTag()
+ {
+ return _deliveryTag;
+ }
+
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
index 94be090cf2..c0d51fa726 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
@@ -31,7 +31,6 @@ import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
/**
* @author Apache Software Foundation
@@ -44,21 +43,21 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
*/
private static final int DEFAULT_BUFFER_INITIAL_SIZE = 1024;
- AbstractBytesMessage()
+ AbstractBytesMessage(AMQMessageDelegateFactory delegateFactory)
{
- this(null);
+ this(delegateFactory, null);
}
/**
* Construct a bytes message with existing data.
*
+ * @param delegateFactory
* @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
- * set to auto expand
*/
- AbstractBytesMessage(ByteBuffer data)
+ AbstractBytesMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(data); // this instanties a content header
- getContentHeaderProperties().setContentType(getMimeTypeAsShortString());
+ super(delegateFactory, data); // this instanties a content header
+ setContentType(getMimeType());
if (_data == null)
{
@@ -72,13 +71,12 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
_data.setAutoExpand(true);
}
- AbstractBytesMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
- {
- // TODO: this casting is ugly. Need to review whole ContentHeaderBody idea
- super(messageNbr, contentHeader, exchange, routingKey, data);
- getContentHeaderProperties().setContentType(getMimeTypeAsShortString());
- }
+ AbstractBytesMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
+ {
+ super(delegate, data);
+ setContentType(getMimeType());
+ }
+
public void clearBodyImpl() throws JMSException
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
index 9bdde01bf3..f0fc394b0b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
@@ -33,7 +33,6 @@ import javax.jms.MessageNotWriteableException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
/**
@@ -70,27 +69,28 @@ public abstract class AbstractBytesTypedMessage extends AbstractBytesMessage
*/
private int _byteArrayRemaining = -1;
- AbstractBytesTypedMessage()
+ AbstractBytesTypedMessage(AMQMessageDelegateFactory delegateFactory)
{
- this(null);
+
+ this(delegateFactory, null);
}
/**
* Construct a stream message with existing data.
*
+ * @param delegateFactory
* @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
- * set to auto expand
*/
- AbstractBytesTypedMessage(ByteBuffer data)
+ AbstractBytesTypedMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(data); // this instanties a content header
- }
+ super(delegateFactory, data); // this instanties a content header
+ }
- AbstractBytesTypedMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ AbstractBytesTypedMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(messageNbr, contentHeader, exchange, routingKey, data);
+
+ super(delegate, data);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
index ab284116af..0700ce5d23 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
@@ -21,10 +21,7 @@
package org.apache.qpid.client.message;
import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.Collections;
import java.util.Enumeration;
-import java.util.Map;
import java.util.UUID;
import javax.jms.Destination;
@@ -32,122 +29,48 @@ import javax.jms.JMSException;
import javax.jms.MessageNotReadableException;
import javax.jms.MessageNotWriteableException;
-import org.apache.commons.collections.map.ReferenceMap;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.AMQUndefinedDestination;
-import org.apache.qpid.client.BasicMessageConsumer;
-import org.apache.qpid.client.CustomJMSXProperty;
-import org.apache.qpid.client.JMSAMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.url.AMQBindingURL;
-import org.apache.qpid.url.BindingURL;
-public abstract class AbstractJMSMessage extends AMQMessage implements org.apache.qpid.jms.Message
+public abstract class AbstractJMSMessage implements org.apache.qpid.jms.Message
{
- private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap());
- public static final String JMS_TYPE = "x-jms-type";
- protected boolean _redelivered;
protected ByteBuffer _data;
- private boolean _readableProperties = false;
protected boolean _readableMessage = false;
protected boolean _changedData = true;
- private Destination _destination;
- private JMSHeaderAdapter _headerAdapter;
- private static final boolean STRICT_AMQP_COMPLIANCE =
- Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT));
- /**
- * This is 0_10 specific
- */
- private org.apache.qpidity.api.Message _010message = null;
+ /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */
- public void set010Message(org.apache.qpidity.api.Message m )
- {
- _010message = m;
- }
-
- public void dataChanged()
- {
- if (_010message != null)
- {
- _010message.clearData();
- try
- {
- if (_data != null)
- {
- _010message.appendData(_data.buf().slice());
- }
- else
- {
- _010message.appendData(java.nio.ByteBuffer.allocate(0));
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
- }
- /**
- * End 010 specific
- */
- public org.apache.qpidity.api.Message get010Message()
- {
- return _010message;
- }
+ private AMQMessageDelegate _delegate;
+ private boolean _redelivered;
- protected AbstractJMSMessage(ByteBuffer data)
+ protected AbstractJMSMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(new BasicContentHeaderProperties());
+ _delegate = delegateFactory.createDelegate();
_data = data;
if (_data != null)
{
_data.acquire();
}
- _readableProperties = false;
+
_readableMessage = (data != null);
_changedData = (data == null);
- _headerAdapter = new JMSHeaderAdapter(((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders());
}
- protected AbstractJMSMessage(long deliveryTag, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ protected AbstractJMSMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- this(contentHeader, deliveryTag);
-
- Integer type = contentHeader.getHeaders().getInteger(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName());
- AMQDestination dest;
-
- if (AMQDestination.QUEUE_TYPE.equals(type))
- {
- dest = new AMQQueue(exchange, routingKey, routingKey);
- }
- else if (AMQDestination.TOPIC_TYPE.equals(type))
- {
- dest = new AMQTopic(exchange, routingKey, null);
- }
- else
- {
- dest = new AMQUndefinedDestination(exchange, routingKey, null);
- }
- // Destination dest = AMQDestination.createDestination(url);
- setJMSDestination(dest);
+ _delegate = delegate;
_data = data;
if (_data != null)
@@ -159,126 +82,82 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
}
- protected AbstractJMSMessage(BasicContentHeaderProperties contentHeader, long deliveryTag)
+ public String getJMSMessageID() throws JMSException
{
- super(contentHeader, deliveryTag);
- _readableProperties = (_contentHeaderProperties != null);
- _headerAdapter = new JMSHeaderAdapter(((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders());
+ return _delegate.getJMSMessageID();
}
- public String getJMSMessageID() throws JMSException
+ public void setJMSMessageID(String messageId) throws JMSException
{
- return getContentHeaderProperties().getMessageIdAsString();
+ _delegate.setJMSMessageID(messageId);
}
- public void setJMSMessageID(String messageId) throws JMSException
+ public void setJMSMessageID(UUID messageId) throws JMSException
{
- getContentHeaderProperties().setMessageId(messageId);
+ _delegate.setJMSMessageID(messageId);
}
+
public long getJMSTimestamp() throws JMSException
{
- return getContentHeaderProperties().getTimestamp();
+ return _delegate.getJMSTimestamp();
}
public void setJMSTimestamp(long timestamp) throws JMSException
{
- getContentHeaderProperties().setTimestamp(timestamp);
+ _delegate.setJMSTimestamp(timestamp);
}
public byte[] getJMSCorrelationIDAsBytes() throws JMSException
{
- return getContentHeaderProperties().getCorrelationIdAsString().getBytes();
+ return _delegate.getJMSCorrelationIDAsBytes();
}
public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
{
- getContentHeaderProperties().setCorrelationId(new String(bytes));
+ _delegate.setJMSCorrelationIDAsBytes(bytes);
}
public void setJMSCorrelationID(String correlationId) throws JMSException
{
- getContentHeaderProperties().setCorrelationId(correlationId);
+ _delegate.setJMSCorrelationID(correlationId);
}
public String getJMSCorrelationID() throws JMSException
{
- return getContentHeaderProperties().getCorrelationIdAsString();
+ return _delegate.getJMSCorrelationID();
}
public Destination getJMSReplyTo() throws JMSException
{
- String replyToEncoding = getContentHeaderProperties().getReplyToAsString();
- if (replyToEncoding == null)
- {
- return null;
- }
- else
- {
- Destination dest = (Destination) _destinationCache.get(replyToEncoding);
- if (dest == null)
- {
- try
- {
- BindingURL binding = new AMQBindingURL(replyToEncoding);
- dest = AMQDestination.createDestination(binding);
- }
- catch (URISyntaxException e)
- {
- throw new JMSAMQException("Illegal value in JMS_ReplyTo property: " + replyToEncoding, e);
- }
-
- _destinationCache.put(replyToEncoding, dest);
- }
-
- return dest;
- }
+ return _delegate.getJMSReplyTo();
}
public void setJMSReplyTo(Destination destination) throws JMSException
{
- if (destination == null)
- {
- throw new IllegalArgumentException("Null destination not allowed");
- }
-
- if (!(destination instanceof AMQDestination))
- {
- throw new IllegalArgumentException(
- "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass());
- }
-
- final AMQDestination amqd = (AMQDestination) destination;
-
- final AMQShortString encodedDestination = amqd.getEncodedName();
- _destinationCache.put(encodedDestination, destination);
- getContentHeaderProperties().setReplyTo(encodedDestination);
+ _delegate.setJMSReplyTo(destination);
}
public Destination getJMSDestination() throws JMSException
{
- return _destination;
+ return _delegate.getJMSDestination();
}
public void setJMSDestination(Destination destination)
{
- _destination = destination;
+ _delegate.setJMSDestination(destination);
}
public int getJMSDeliveryMode() throws JMSException
{
- return getContentHeaderProperties().getDeliveryMode();
+ return _delegate.getJMSDeliveryMode();
}
public void setJMSDeliveryMode(int i) throws JMSException
{
- getContentHeaderProperties().setDeliveryMode((byte) i);
+ _delegate.setJMSDeliveryMode(i);
}
- public BasicContentHeaderProperties getContentHeaderProperties()
- {
- return (BasicContentHeaderProperties) _contentHeaderProperties;
- }
public boolean getJMSRedelivered() throws JMSException
{
@@ -290,318 +169,180 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
_redelivered = b;
}
+
public String getJMSType() throws JMSException
{
- return getContentHeaderProperties().getTypeAsString();
+ return _delegate.getJMSType();
}
public void setJMSType(String string) throws JMSException
{
- getContentHeaderProperties().setType(string);
+ _delegate.setJMSType(string);
}
public long getJMSExpiration() throws JMSException
{
- return getContentHeaderProperties().getExpiration();
+ return _delegate.getJMSExpiration();
}
public void setJMSExpiration(long l) throws JMSException
{
- getContentHeaderProperties().setExpiration(l);
+ _delegate.setJMSExpiration(l);
}
public int getJMSPriority() throws JMSException
{
- return getContentHeaderProperties().getPriority();
+ return _delegate.getJMSPriority();
}
public void setJMSPriority(int i) throws JMSException
{
- getContentHeaderProperties().setPriority((byte) i);
- }
-
- public void clearProperties() throws JMSException
- {
- getJmsHeaders().clear();
-
- _readableProperties = false;
- }
-
- public void clearBody() throws JMSException
- {
- clearBodyImpl();
- _readableMessage = false;
+ _delegate.setJMSPriority(i);
}
- public boolean propertyExists(AMQShortString propertyName) throws JMSException
- {
- return getJmsHeaders().propertyExists(propertyName);
- }
public boolean propertyExists(String propertyName) throws JMSException
{
- return getJmsHeaders().propertyExists(propertyName);
+ return _delegate.propertyExists(propertyName);
}
- public boolean getBooleanProperty(AMQShortString propertyName) throws JMSException
+ public boolean getBooleanProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getBoolean(propertyName);
+ return _delegate.getBooleanProperty(s);
}
- public boolean getBooleanProperty(String propertyName) throws JMSException
+ public byte getByteProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getBoolean(propertyName);
+ return _delegate.getByteProperty(s);
}
- public byte getByteProperty(String propertyName) throws JMSException
+ public short getShortProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getByte(propertyName);
+ return _delegate.getShortProperty(s);
}
- public byte[] getBytesProperty(AMQShortString propertyName) throws JMSException
+ public int getIntProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getBytes(propertyName);
+ return _delegate.getIntProperty(s);
}
- public short getShortProperty(String propertyName) throws JMSException
+ public long getLongProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getShort(propertyName);
+ return _delegate.getLongProperty(s);
}
- public int getIntProperty(String propertyName) throws JMSException
+ public float getFloatProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getInteger(propertyName);
+ return _delegate.getFloatProperty(s);
}
- public long getLongProperty(String propertyName) throws JMSException
+ public double getDoubleProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getLong(propertyName);
- }
-
- public float getFloatProperty(String propertyName) throws JMSException
- {
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getFloat(propertyName);
+ return _delegate.getDoubleProperty(s);
}
- public double getDoubleProperty(String propertyName) throws JMSException
+ public String getStringProperty(final String s)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getDouble(propertyName);
+ return _delegate.getStringProperty(s);
}
- public String getStringProperty(String propertyName) throws JMSException
+ public Object getObjectProperty(final String s)
+ throws JMSException
{
- //NOTE: if the JMSX Property is a non AMQP property then we must check _strictAMQP and throw as below.
- if (propertyName.equals(CustomJMSXProperty.JMSXUserID.toString()))
- {
- return ((BasicContentHeaderProperties) _contentHeaderProperties).getUserIdAsString();
- }
- else
- {
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- return getJmsHeaders().getString(propertyName);
- }
+ return _delegate.getObjectProperty(s);
}
- public Object getObjectProperty(String propertyName) throws JMSException
+ public Enumeration getPropertyNames()
+ throws JMSException
{
- return getJmsHeaders().getObject(propertyName);
+ return _delegate.getPropertyNames();
}
- public Enumeration getPropertyNames() throws JMSException
+ public void setBooleanProperty(final String s, final boolean b)
+ throws JMSException
{
- return getJmsHeaders().getPropertyNames();
+ _delegate.setBooleanProperty(s, b);
}
- public void setBooleanProperty(AMQShortString propertyName, boolean b) throws JMSException
+ public void setByteProperty(final String s, final byte b)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setBoolean(propertyName, b);
+ _delegate.setByteProperty(s, b);
}
- public void setBooleanProperty(String propertyName, boolean b) throws JMSException
+ public void setShortProperty(final String s, final short i)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setBoolean(propertyName, b);
+ _delegate.setShortProperty(s, i);
}
- public void setByteProperty(String propertyName, byte b) throws JMSException
+ public void setIntProperty(final String s, final int i)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setByte(propertyName, new Byte(b));
+ _delegate.setIntProperty(s, i);
}
- public void setBytesProperty(AMQShortString propertyName, byte[] bytes) throws JMSException
+ public void setLongProperty(final String s, final long l)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setBytes(propertyName, bytes);
+ _delegate.setLongProperty(s, l);
}
- public void setShortProperty(String propertyName, short i) throws JMSException
+ public void setFloatProperty(final String s, final float v)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setShort(propertyName, new Short(i));
+ _delegate.setFloatProperty(s, v);
}
- public void setIntProperty(String propertyName, int i) throws JMSException
+ public void setDoubleProperty(final String s, final double v)
+ throws JMSException
{
- checkWritableProperties();
- JMSHeaderAdapter.checkPropertyName(propertyName);
- super.setIntProperty(new AMQShortString(propertyName), new Integer(i));
+ _delegate.setDoubleProperty(s, v);
}
- public void setLongProperty(String propertyName, long l) throws JMSException
+ public void setStringProperty(final String s, final String s1)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setLong(propertyName, new Long(l));
+ _delegate.setStringProperty(s, s1);
}
- public void setFloatProperty(String propertyName, float f) throws JMSException
+ public void setObjectProperty(final String s, final Object o)
+ throws JMSException
{
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
-
- checkWritableProperties();
- getJmsHeaders().setFloat(propertyName, new Float(f));
+ _delegate.setObjectProperty(s, o);
}
- public void setDoubleProperty(String propertyName, double v) throws JMSException
- {
- if (STRICT_AMQP_COMPLIANCE)
- {
- throw new UnsupportedOperationException("JMS Proprerties not supported in AMQP");
- }
- checkWritableProperties();
- getJmsHeaders().setDouble(propertyName, new Double(v));
- }
- public void setStringProperty(String propertyName, String value) throws JMSException
+ public void clearProperties() throws JMSException
{
- checkWritableProperties();
- JMSHeaderAdapter.checkPropertyName(propertyName);
- super.setLongStringProperty(new AMQShortString(propertyName), value);
+ _delegate.clearProperties();
}
- public void setObjectProperty(String propertyName, Object object) throws JMSException
+ public void clearBody() throws JMSException
{
- checkWritableProperties();
- getJmsHeaders().setObject(propertyName, object);
- }
+ clearBodyImpl();
+ _readableMessage = false;
- protected void removeProperty(AMQShortString propertyName) throws JMSException
- {
- getJmsHeaders().remove(propertyName);
}
- protected void removeProperty(String propertyName) throws JMSException
- {
- getJmsHeaders().remove(propertyName);
- }
public void acknowledgeThis() throws JMSException
{
- // the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
- // is not specified. In our case, we only set the session field where client acknowledge mode is specified.
- if (_session != null)
- {
- if (_session.getAMQConnection().isClosed())
- {
- throw new javax.jms.IllegalStateException("Connection is already closed");
- }
-
- // we set multiple to true here since acknowledgement implies acknowledge of all previous messages
- // received on the session
- _session.acknowledgeMessage(_deliveryTag, true);
- }
+ _delegate.acknowledgeThis();
}
public void acknowledge() throws JMSException
{
- if (_session != null)
- {
- _session.acknowledge();
- }
+ _delegate.acknowledge();
}
/**
@@ -617,12 +358,9 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
*/
public abstract String toBodyString() throws JMSException;
- public String getMimeType()
- {
- return getMimeTypeAsShortString().toString();
- }
+ protected abstract String getMimeType();
+
- public abstract AMQShortString getMimeTypeAsShortString();
public String toString()
{
@@ -640,16 +378,23 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
buf.append("\nJMS Destination: ").append(getJMSDestination());
buf.append("\nJMS Type: ").append(getJMSType());
buf.append("\nJMS MessageID: ").append(getJMSMessageID());
- buf.append("\nAMQ message number: ").append(_deliveryTag);
+ buf.append("\nAMQ message number: ").append(getDeliveryTag());
buf.append("\nProperties:");
- if (getJmsHeaders().isEmpty())
+ final Enumeration propertyNames = getPropertyNames();
+ if (!propertyNames.hasMoreElements())
{
buf.append("<NONE>");
}
else
{
- buf.append('\n').append(getJmsHeaders().getHeaders());
+ buf.append('\n');
+ while(propertyNames.hasMoreElements())
+ {
+ String propertyName = (String) propertyNames.nextElement();
+ buf.append(propertyName).append(":\t").append(getObjectProperty(propertyName));
+ }
+
}
return buf.toString();
@@ -660,14 +405,10 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
}
}
- public void setUnderlyingMessagePropertiesMap(FieldTable messageProperties)
- {
- getContentHeaderProperties().setHeaders(messageProperties);
- }
- public JMSHeaderAdapter getJmsHeaders()
+ public AMQMessageDelegate getDelegate()
{
- return _headerAdapter;
+ return _delegate;
}
public ByteBuffer getData()
@@ -698,25 +439,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
}
}
- protected void checkWritableProperties() throws MessageNotWriteableException
- {
- if (_readableProperties)
- {
- throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
- }
- _contentHeaderProperties.updated();
- }
-
- public boolean isReadable()
- {
- return _readableMessage;
- }
-
- public boolean isWritable()
- {
- return !_readableMessage;
- }
-
public void reset()
{
if (!_changedData)
@@ -726,7 +448,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
else
{
_data.flip();
- dataChanged();
_changedData = false;
}
}
@@ -748,4 +469,66 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
_changedData = false;
}
+ /**
+ * The session is set when CLIENT_ACKNOWLEDGE mode is used so that the CHANNEL ACK can be sent when the user calls
+ * acknowledge()
+ *
+ * @param s the AMQ session that delivered this message
+ */
+ public void setAMQSession(AMQSession s)
+ {
+ _delegate.setAMQSession(s);
+ }
+
+ public AMQSession getAMQSession()
+ {
+ return _delegate.getAMQSession();
+ }
+
+ /**
+ * Get the AMQ message number assigned to this message
+ *
+ * @return the message number
+ */
+ public long getDeliveryTag()
+ {
+ return _delegate.getDeliveryTag();
+ }
+
+ /** Invoked prior to sending the message. Allows the message to be modified if necessary before sending. */
+ public void prepareForSending() throws JMSException
+ {
+ }
+
+
+ public void setContentType(String contentType)
+ {
+ _delegate.setContentType(contentType);
+ }
+
+ public String getContentType()
+ {
+ return _delegate.getContentType();
+ }
+
+ public void setEncoding(String encoding)
+ {
+ _delegate.setEncoding(encoding);
+ }
+
+ public String getEncoding()
+ {
+ return _delegate.getEncoding();
+ }
+
+ public String getReplyToString()
+ {
+ return _delegate.getReplyToString();
+ }
+
+ protected void removeProperty(final String propertyName) throws JMSException
+ {
+ _delegate.removeProperty(propertyName);
+ }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
index 0dbad3726c..54a845ceef 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java
@@ -27,9 +27,9 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpidity.transport.Struct;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.DeliveryProperties;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.DeliveryProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,17 +38,11 @@ import javax.jms.JMSException;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
public abstract class AbstractJMSMessageFactory implements MessageFactory
{
private static final Logger _logger = LoggerFactory.getLogger(AbstractJMSMessageFactory.class);
- protected abstract AbstractJMSMessage createMessage(long messageNbr, ByteBuffer data, AMQShortString exchange,
- AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException;
-
protected AbstractJMSMessage create08MessageWithBody(long messageNbr, ContentHeaderBody contentHeader,
AMQShortString exchange, AMQShortString routingKey,
List bodies) throws AMQException
@@ -105,23 +99,28 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
.remaining());
}
- return createMessage(messageNbr, data, exchange, routingKey,
- (BasicContentHeaderProperties) contentHeader.properties);
+ AMQMessageDelegate delegate = new AMQMessageDelegate_0_8(messageNbr,
+ (BasicContentHeaderProperties) contentHeader.properties,
+ exchange, routingKey);
+
+ return createMessage(delegate, data);
}
+ protected abstract AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException;
+
+
protected AbstractJMSMessage create010MessageWithBody(long messageNbr, Struct[] contentHeader,
- AMQShortString exchange, AMQShortString routingKey,
- List bodies, String replyToURL) throws AMQException
+ java.nio.ByteBuffer body) throws AMQException
{
ByteBuffer data;
final boolean debug = _logger.isDebugEnabled();
- // we optimise the non-fragmented case to avoid copying
- if ((bodies != null))
+
+ if (body != null)
{
- data = ByteBuffer.wrap((java.nio.ByteBuffer) bodies.get(0));
+ data = ByteBuffer.wrap(body);
}
- else // bodies == null
+ else // body == null
{
data = ByteBuffer.allocate(0);
}
@@ -131,40 +130,13 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
_logger.debug("Creating message from buffer with position=" + data.position() + " and remaining=" + data
.remaining());
}
- BasicContentHeaderProperties props = new BasicContentHeaderProperties();
// set the properties of this message
MessageProperties mprop = (MessageProperties) contentHeader[0];
DeliveryProperties devprop = (DeliveryProperties) contentHeader[1];
- props.setContentType(mprop.getContentType());
- props.setCorrelationId(asString(mprop.getCorrelationId()));
- String encoding = mprop.getContentEncoding();
- if (encoding != null && !encoding.equals(""))
- {
- props.setEncoding(encoding);
- }
- if (devprop.hasDeliveryMode())
- {
- props.setDeliveryMode((byte) devprop.getDeliveryMode().getValue());
- }
- props.setExpiration(devprop.getExpiration());
- UUID mid = mprop.getMessageId();
- props.setMessageId(mid == null ? null : "ID:" + mid.toString());
- if (devprop.hasPriority())
- {
- props.setPriority((byte) devprop.getPriority().getValue());
- }
- props.setReplyTo(replyToURL);
- props.setTimestamp(devprop.getTimestamp());
- String type = null;
- Map<String,Object> map = mprop.getApplicationHeaders();
- if (map != null)
- {
- type = (String) map.get(AbstractJMSMessage.JMS_TYPE);
- }
- props.setType(type);
- props.setUserId(asString(mprop.getUserId()));
- props.setHeaders(FiledTableSupport.convertToFieldTable(mprop.getApplicationHeaders()));
- AbstractJMSMessage message = createMessage(messageNbr, data, exchange, routingKey, props);
+
+ AMQMessageDelegate delegate = new AMQMessageDelegate_0_10(mprop, devprop, messageNbr);
+
+ AbstractJMSMessage message = createMessage(delegate, data);
return message;
}
@@ -192,12 +164,11 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory
}
public AbstractJMSMessage createMessage(long messageNbr, boolean redelivered, Struct[] contentHeader,
- AMQShortString exchange, AMQShortString routingKey, List bodies,
- String replyToURL)
+ java.nio.ByteBuffer body)
throws JMSException, AMQException
{
final AbstractJMSMessage msg =
- create010MessageWithBody(messageNbr, contentHeader, exchange, routingKey, bodies, replyToURL);
+ create010MessageWithBody(messageNbr, contentHeader, body);
msg.setJMSRedelivered(redelivered);
msg.receivedFromServer();
return msg;
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/CloseConsumerMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/CloseConsumerMessage.java
new file mode 100644
index 0000000000..4af04912e5
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/message/CloseConsumerMessage.java
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.message;
+
+import org.apache.qpid.client.BasicMessageConsumer;
+
+public final class CloseConsumerMessage extends UnprocessedMessage
+{
+
+ public CloseConsumerMessage(BasicMessageConsumer consumer)
+ {
+ super(consumer.getConsumerTag());
+ }
+
+
+ public long getDeliveryTag()
+ {
+ return 0;
+ }
+
+ public boolean isRedelivered()
+ {
+ return false;
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
index 4f5641bcff..cd9d7ccf8b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
@@ -33,46 +33,47 @@ import javax.jms.MessageFormatException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSBytesMessage extends AbstractBytesMessage implements BytesMessage
{
public static final String MIME_TYPE = "application/octet-stream";
- private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE);
- public JMSBytesMessage()
+
+ public JMSBytesMessage(AMQMessageDelegateFactory delegateFactory)
{
- this(null);
+ this(delegateFactory,null);
+
}
/**
* Construct a bytes message with existing data.
*
+ * @param delegateFactory
* @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
- * set to auto expand
*/
- JMSBytesMessage(ByteBuffer data)
+ JMSBytesMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(data); // this instanties a content header
+
+ super(delegateFactory, data); // this instanties a content header
}
- JMSBytesMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ JMSBytesMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(messageNbr, contentHeader, exchange, routingKey, data);
+ super(delegate, data);
}
+
public void reset()
{
super.reset();
_readableMessage = true;
}
- public AMQShortString getMimeTypeAsShortString()
+ protected String getMimeType()
{
- return MIME_TYPE_SHORT_STRING;
+ return MIME_TYPE;
}
public long getBodyLength() throws JMSException
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
index 0202dc29df..cb04ebee1b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessageFactory.java
@@ -25,21 +25,18 @@ import javax.jms.JMSException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSBytesMessageFactory extends AbstractJMSMessageFactory
{
- protected AbstractJMSMessage createMessage(long deliveryTag, ByteBuffer data,
- AMQShortString exchange, AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException
+ protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- return new JMSBytesMessage(deliveryTag, contentHeader, exchange, routingKey, data);
+ return new JMSBytesMessage(delegate, data);
}
- public AbstractJMSMessage createMessage() throws JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- return new JMSBytesMessage();
+ return new JMSBytesMessage(delegateFactory);
}
// 0_10 specific
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
index fec0117a03..6215652c80 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
@@ -467,7 +467,7 @@ public final class JMSHeaderAdapter
return getPropertyNames();
}
- protected static void checkPropertyName(CharSequence propertyName)
+ protected void checkPropertyName(CharSequence propertyName)
{
if (propertyName == null)
{
@@ -481,7 +481,7 @@ public final class JMSHeaderAdapter
checkIdentiferFormat(propertyName);
}
- protected static void checkIdentiferFormat(CharSequence propertyName)
+ protected void checkIdentiferFormat(CharSequence propertyName)
{
// JMS requirements 3.5.1 Property Names
// Identifiers:
@@ -492,14 +492,14 @@ public final class JMSHeaderAdapter
// '_' and '$'. An identifier part character is any character for which the
// method Character.isJavaIdentifierPart returns true.
// - Identifiers cannot be the names NULL, TRUE, or FALSE.
-// � Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
+// Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
// ESCAPE.
-// � Identifiers are either header field references or property references. The
+// Identifiers are either header field references or property references. The
// type of a property value in a message selector corresponds to the type
// used to set the property. If a property that does not exist in a message is
// referenced, its value is NULL. The semantics of evaluating NULL values
-// in a selector are described in Section 3.8.1.2, �Null Values.�
-// � The conversions that apply to the get methods for properties do not
+// in a selector are described in Section 3.8.1.2, Null Values.
+// The conversions that apply to the get methods for properties do not
// apply when a property is used in a message selector expression. For
// example, suppose you set a property as a string value, as in the
// following:
@@ -507,8 +507,8 @@ public final class JMSHeaderAdapter
// The following expression in a message selector would evaluate to false,
// because a string cannot be used in an arithmetic expression:
// "NumberOfOrders > 1"
-// � Identifiers are case sensitive.
-// � Message header field references are restricted to JMSDeliveryMode,
+// Identifiers are case sensitive.
+// Message header field references are restricted to JMSDeliveryMode,
// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
// null and if so are treated as a NULL value.
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
index fed1f1c609..b6e013ac8f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
@@ -24,7 +24,6 @@ import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.slf4j.Logger;
@@ -44,18 +43,19 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm
private static final Logger _logger = LoggerFactory.getLogger(JMSMapMessage.class);
public static final String MIME_TYPE = "jms/map-message";
- private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE);
+
private Map<String, Object> _map = new HashMap<String, Object>();
- public JMSMapMessage() throws JMSException
+ public JMSMapMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- this(null);
+ this(delegateFactory, null);
}
- JMSMapMessage(ByteBuffer data) throws JMSException
+ JMSMapMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data) throws JMSException
{
- super(data); // this instantiates a content header
+
+ super(delegateFactory, data); // this instantiates a content header
if(data != null)
{
populateMapFromData();
@@ -63,10 +63,10 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm
}
- JMSMapMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange, AMQShortString routingKey,
- ByteBuffer data) throws AMQException
+ JMSMapMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(messageNbr, contentHeader, exchange, routingKey, data);
+
+ super(delegate, data);
try
{
populateMapFromData();
@@ -79,14 +79,15 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm
}
+
public String toBodyString() throws JMSException
{
return _map == null ? "" : _map.toString();
}
- public AMQShortString getMimeTypeAsShortString()
+ protected String getMimeType()
{
- return MIME_TYPE_SHORT_STRING;
+ return MIME_TYPE;
}
public ByteBuffer getData()
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
index 7cb8b637e6..eccb90560b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessageFactory.java
@@ -25,21 +25,18 @@ import javax.jms.JMSException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSMapMessageFactory extends AbstractJMSMessageFactory
{
- public AbstractJMSMessage createMessage() throws JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- return new JMSMapMessage();
+ return new JMSMapMessage(delegateFactory);
}
- protected AbstractJMSMessage createMessage(long deliveryTag, ByteBuffer data,
- AMQShortString exchange, AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException
+ protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- return new JMSMapMessage(deliveryTag, contentHeader, exchange, routingKey, data);
+ return new JMSMapMessage(delegate, data);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
index 385eee47c9..39b9597af1 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
@@ -37,63 +37,65 @@ import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessage
{
public static final String MIME_TYPE = "application/java-object-stream";
- private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE);
+
private static final int DEFAULT_BUFFER_SIZE = 1024;
/**
* Creates empty, writable message for use by producers
+ * @param delegateFactory
*/
- public JMSObjectMessage()
+ public JMSObjectMessage(AMQMessageDelegateFactory delegateFactory)
{
- this(null);
+ this(delegateFactory, null);
}
- private JMSObjectMessage(ByteBuffer data)
+ private JMSObjectMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(data);
+ super(delegateFactory, data);
if (data == null)
{
_data = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
_data.setAutoExpand(true);
}
- getContentHeaderProperties().setContentType(MIME_TYPE_SHORT_STRING);
+ setContentType(getMimeType());
}
/**
* Creates read only message for delivery to consumers
*/
- JMSObjectMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange, AMQShortString routingKey,
- ByteBuffer data) throws AMQException
- {
- super(messageNbr, contentHeader, exchange, routingKey, data);
- }
+
+ JMSObjectMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
+ {
+ super(delegate, data);
+ }
+
public void clearBodyImpl() throws JMSException
{
if (_data != null)
{
_data.release();
+ _data = null;
}
- _data = null;
+
}
public String toBodyString() throws JMSException
{
- return toString(_data);
+ return String.valueOf(getObject());
}
- public AMQShortString getMimeTypeAsShortString()
+ public String getMimeType()
{
- return MIME_TYPE_SHORT_STRING;
+ return MIME_TYPE;
}
public void setObject(Serializable serializable) throws JMSException
@@ -172,26 +174,4 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
catch (IOException ignore)
{ }
}
-
- private static String toString(ByteBuffer data)
- {
- if (data == null)
- {
- return null;
- }
-
- int pos = data.position();
- try
- {
- return data.getString(Charset.forName("UTF8").newDecoder());
- }
- catch (CharacterCodingException e)
- {
- return null;
- }
- finally
- {
- data.position(pos);
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
index e7369dcb26..03851dfa01 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessageFactory.java
@@ -25,20 +25,17 @@ import javax.jms.JMSException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSObjectMessageFactory extends AbstractJMSMessageFactory
{
- protected AbstractJMSMessage createMessage(long deliveryTag, ByteBuffer data,
- AMQShortString exchange, AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException
+ protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- return new JMSObjectMessage(deliveryTag, contentHeader, exchange, routingKey, data);
+ return new JMSObjectMessage(delegate, data);
}
- public AbstractJMSMessage createMessage() throws JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- return new JMSObjectMessage();
+ return new JMSObjectMessage(delegateFactory);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
index 62f3150ed1..ad2620852b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
@@ -26,7 +26,6 @@ import javax.jms.StreamMessage;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
/**
@@ -35,7 +34,7 @@ import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSStreamMessage extends AbstractBytesTypedMessage implements StreamMessage
{
public static final String MIME_TYPE="jms/stream-message";
- private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE);
+
/**
@@ -44,38 +43,40 @@ public class JMSStreamMessage extends AbstractBytesTypedMessage implements Strea
*/
private int _byteArrayRemaining = -1;
- public JMSStreamMessage()
+ public JMSStreamMessage(AMQMessageDelegateFactory delegateFactory)
{
- this(null);
+ this(delegateFactory,null);
+
}
/**
* Construct a stream message with existing data.
*
+ * @param delegateFactory
* @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
- * set to auto expand
*/
- JMSStreamMessage(ByteBuffer data)
+ JMSStreamMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data)
{
- super(data); // this instanties a content header
- }
+ super(delegateFactory, data); // this instanties a content header
+ }
- JMSStreamMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ JMSStreamMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- super(messageNbr, contentHeader, exchange, routingKey, data);
+
+ super(delegate, data);
}
+
public void reset()
{
super.reset();
_readableMessage = true;
}
- public AMQShortString getMimeTypeAsShortString()
+ protected String getMimeType()
{
- return MIME_TYPE_SHORT_STRING;
+ return MIME_TYPE;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
index 4bb648e090..5e25db9ae0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessageFactory.java
@@ -25,19 +25,16 @@ import javax.jms.JMSException;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
public class JMSStreamMessageFactory extends AbstractJMSMessageFactory
{
- protected AbstractJMSMessage createMessage(long deliveryTag, ByteBuffer data,
- AMQShortString exchange, AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException
+ protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- return new JMSStreamMessage(deliveryTag, contentHeader, exchange, routingKey, data);
+ return new JMSStreamMessage(delegate, data);
}
- public AbstractJMSMessage createMessage() throws JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- return new JMSStreamMessage();
+ return new JMSStreamMessage(delegateFactory);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
index 4a43a7bba8..c290149cef 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessage.java
@@ -31,60 +31,49 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.client.CustomJMSXProperty;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.util.Strings;
public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.TextMessage
{
private static final String MIME_TYPE = "text/plain";
- private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE);
-
private String _decodedValue;
/**
* This constant represents the name of a property that is set when the message payload is null.
*/
- private static final AMQShortString PAYLOAD_NULL_PROPERTY = CustomJMSXProperty.JMS_AMQP_NULL.getShortStringName();
+ private static final String PAYLOAD_NULL_PROPERTY = CustomJMSXProperty.JMS_AMQP_NULL.toString();
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
- public JMSTextMessage() throws JMSException
+ public JMSTextMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- this(null, null);
+ this(delegateFactory, null, null);
}
- JMSTextMessage(ByteBuffer data, String encoding) throws JMSException
+ JMSTextMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data, String encoding) throws JMSException
{
- super(data); // this instantiates a content header
- getContentHeaderProperties().setContentType(MIME_TYPE_SHORT_STRING);
- getContentHeaderProperties().setEncoding(encoding);
+ super(delegateFactory, data); // this instantiates a content header
+ setContentType(getMimeType());
+ setEncoding(encoding);
}
- JMSTextMessage(long deliveryTag, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data)
+ JMSTextMessage(AMQMessageDelegate delegate, ByteBuffer data)
throws AMQException
{
- super(deliveryTag, contentHeader, exchange, routingKey, data);
- contentHeader.setContentType(MIME_TYPE_SHORT_STRING);
+ super(delegate, data);
+ setContentType(getMimeType());
_data = data;
}
- JMSTextMessage(ByteBuffer data) throws JMSException
- {
- this(data, null);
- }
-
- JMSTextMessage(String text) throws JMSException
- {
- super((ByteBuffer) null);
- setText(text);
- }
public void clearBodyImpl() throws JMSException
{
if (_data != null)
{
_data.release();
+ _data = null;
}
- _data = null;
+
_decodedValue = null;
}
@@ -93,14 +82,9 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
return getText();
}
- public void setData(ByteBuffer data)
+ protected String getMimeType()
{
- _data = data;
- }
-
- public AMQShortString getMimeTypeAsShortString()
- {
- return MIME_TYPE_SHORT_STRING;
+ return MIME_TYPE;
}
public void setText(String text) throws JMSException
@@ -111,20 +95,17 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
try
{
if (text != null)
- {
- _data = ByteBuffer.allocate(text.length());
- _data.limit(text.length()) ;
- //_data.sweep();
- _data.setAutoExpand(true);
- final String encoding = getContentHeaderProperties().getEncodingAsString();
- if (encoding == null)
+ {
+ final String encoding = getEncoding();
+ if (encoding == null || encoding.equalsIgnoreCase("UTF-8"))
{
- _data.put(text.getBytes(DEFAULT_CHARSET.name()));
+ _data = ByteBuffer.wrap(Strings.toUTF8(text));
}
else
{
- _data.put(text.getBytes(encoding));
+ _data = ByteBuffer.wrap(text.getBytes(encoding));
}
+ _data.position(_data.limit());
_changedData=true;
}
_decodedValue = text;
@@ -156,11 +137,11 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
{
return null;
}
- if (getContentHeaderProperties().getEncodingAsString() != null)
+ if (getEncoding() != null)
{
try
{
- _decodedValue = _data.getString(Charset.forName(getContentHeaderProperties().getEncodingAsString()).newDecoder());
+ _decodedValue = _data.getString(Charset.forName(getEncoding()).newDecoder());
}
catch (CharacterCodingException e)
{
@@ -199,4 +180,6 @@ public class JMSTextMessage extends AbstractJMSMessage implements javax.jms.Text
removeProperty(PAYLOAD_NULL_PROPERTY);
}
}
+
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
index c578c15a6a..1f4d64c78f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSTextMessageFactory.java
@@ -26,21 +26,17 @@ import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
public class JMSTextMessageFactory extends AbstractJMSMessageFactory
{
- public AbstractJMSMessage createMessage() throws JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
- return new JMSTextMessage();
+ return new JMSTextMessage(delegateFactory);
}
- protected AbstractJMSMessage createMessage(long deliveryTag, ByteBuffer data,
- AMQShortString exchange, AMQShortString routingKey,
- BasicContentHeaderProperties contentHeader) throws AMQException
+ protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException
{
- return new JMSTextMessage(deliveryTag, contentHeader,
- exchange, routingKey, data);
+ return new JMSTextMessage(delegate, data);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
index f6b11c6f6c..e606ef11c9 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java
@@ -22,15 +22,9 @@ package org.apache.qpid.client.message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.client.AMQSession;
-import javax.jms.BytesMessage;
-import javax.jms.JMSException;
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.MessageEOFException;
-import javax.jms.ObjectMessage;
-import javax.jms.StreamMessage;
-import javax.jms.TextMessage;
+import javax.jms.*;
import java.util.Enumeration;
@@ -52,12 +46,11 @@ public class MessageConverter
_newMessage = message;
}
- public MessageConverter(BytesMessage message) throws JMSException
+ public MessageConverter(AMQSession session, BytesMessage bytesMessage) throws JMSException
{
- BytesMessage bytesMessage = (BytesMessage) message;
bytesMessage.reset();
- JMSBytesMessage nativeMsg = new JMSBytesMessage();
+ JMSBytesMessage nativeMsg = (JMSBytesMessage) session.createBytesMessage();
byte[] buf = new byte[1024];
@@ -69,12 +62,12 @@ public class MessageConverter
}
_newMessage = nativeMsg;
- setMessageProperties(message);
+ setMessageProperties(bytesMessage);
}
- public MessageConverter(MapMessage message) throws JMSException
+ public MessageConverter(AMQSession session, MapMessage message) throws JMSException
{
- MapMessage nativeMessage = new JMSMapMessage();
+ MapMessage nativeMessage = session.createMapMessage();
Enumeration mapNames = message.getMapNames();
while (mapNames.hasMoreElements())
@@ -87,21 +80,21 @@ public class MessageConverter
setMessageProperties(message);
}
- public MessageConverter(ObjectMessage message) throws JMSException
+ public MessageConverter(AMQSession session, ObjectMessage origMessage) throws JMSException
{
- ObjectMessage origMessage = (ObjectMessage) message;
- ObjectMessage nativeMessage = new JMSObjectMessage();
+
+ ObjectMessage nativeMessage = session.createObjectMessage();
nativeMessage.setObject(origMessage.getObject());
_newMessage = (AbstractJMSMessage) nativeMessage;
- setMessageProperties(message);
+ setMessageProperties(origMessage);
}
- public MessageConverter(TextMessage message) throws JMSException
+ public MessageConverter(AMQSession session, TextMessage message) throws JMSException
{
- TextMessage nativeMessage = new JMSTextMessage();
+ TextMessage nativeMessage = session.createTextMessage();
nativeMessage.setText(message.getText());
@@ -109,9 +102,9 @@ public class MessageConverter
setMessageProperties(message);
}
- public MessageConverter(StreamMessage message) throws JMSException
+ public MessageConverter(AMQSession session, StreamMessage message) throws JMSException
{
- StreamMessage nativeMessage = new JMSStreamMessage();
+ StreamMessage nativeMessage = session.createStreamMessage();
try
{
@@ -130,11 +123,11 @@ public class MessageConverter
setMessageProperties(message);
}
- public MessageConverter(Message message) throws JMSException
+ public MessageConverter(AMQSession session, Message message) throws JMSException
{
// Send a message with just properties.
// Throwing away content
- BytesMessage nativeMessage = new JMSBytesMessage();
+ Message nativeMessage = session.createMessage();
_newMessage = (AbstractJMSMessage) nativeMessage;
setMessageProperties(message);
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java
index c6b22592e0..e1275c37f7 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactory.java
@@ -27,7 +27,7 @@ import javax.jms.JMSException;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpidity.transport.Struct;
+import org.apache.qpid.transport.Struct;
public interface MessageFactory
@@ -39,10 +39,9 @@ public interface MessageFactory
throws JMSException, AMQException;
AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered,
- Struct[] contentHeader,
- AMQShortString exchange, AMQShortString routingKey,
- List bodies, String replyToURL)
+ Struct[] contentHeader,
+ java.nio.ByteBuffer body)
throws JMSException, AMQException;
- AbstractJMSMessage createMessage() throws JMSException;
+ AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
index 24ab471f10..948d6d0d7d 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java
@@ -23,6 +23,7 @@ package org.apache.qpid.client.message;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.nio.ByteBuffer;
import javax.jms.JMSException;
@@ -30,9 +31,10 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpidity.transport.Struct;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.MessageTransfer;
+import org.apache.qpid.transport.DeliveryProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -92,8 +94,7 @@ public class MessageFactoryRegistry
* @param deliveryTag the AMQ message id
* @param redelivered true if redelivered
* @param contentHeader the content header that was received
- * @param bodies a list of ContentBody instances
- * @return the message.
+ * @param bodies a list of ContentBody instances @return the message.
* @throws AMQException
* @throws JMSException
*/
@@ -120,30 +121,35 @@ public class MessageFactoryRegistry
}
}
- public AbstractJMSMessage createMessage(long deliveryTag, boolean redelivered, AMQShortString exchange,
- AMQShortString routingKey, Struct[] contentHeader, List bodies,
- String replyTo) throws AMQException, JMSException
+ public AbstractJMSMessage createMessage(MessageTransfer transfer) throws AMQException, JMSException
{
- MessageProperties mprop = (MessageProperties) contentHeader[0];
+
+ MessageProperties mprop = transfer.getHeader().get(MessageProperties.class);
String messageType = mprop.getContentType();
if (messageType == null)
{
_logger.debug("no message type specified, building a byte message");
messageType = JMSBytesMessage.MIME_TYPE;
}
- MessageFactory mf = _mimeShortStringToFactoryMap.get(new AMQShortString(messageType));
+ MessageFactory mf = _mimeStringToFactoryMap.get(messageType);
if (mf == null)
{
throw new AMQException(null, "Unsupport MIME type of " + messageType, null);
}
else
{
- return mf.createMessage(deliveryTag, redelivered, contentHeader, exchange, routingKey, bodies, replyTo);
+ boolean redelivered = false;
+ DeliveryProperties deliverProps;
+ if((deliverProps = transfer.getHeader().get(DeliveryProperties.class)) != null)
+ {
+ redelivered = deliverProps.getRedelivered();
+ }
+ return mf.createMessage(transfer.getId(), redelivered, transfer.getHeader().getStructs(), transfer.getBody());
}
}
- public AbstractJMSMessage createMessage(String mimeType) throws AMQException, JMSException
+ public AbstractJMSMessage createMessage(AMQMessageDelegateFactory delegateFactory, String mimeType) throws AMQException, JMSException
{
if (mimeType == null)
{
@@ -157,7 +163,7 @@ public class MessageFactoryRegistry
}
else
{
- return mf.createMessage();
+ return mf.createMessage(delegateFactory);
}
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
index c866a5028e..ed590772d9 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/ReturnMessage.java
@@ -7,9 +7,9 @@ public class ReturnMessage extends UnprocessedMessage_0_8
final private AMQShortString _replyText;
final private int _replyCode;
- public ReturnMessage(int channelId,AMQShortString exchange,AMQShortString routingKey,AMQShortString replyText,int replyCode)
+ public ReturnMessage(AMQShortString exchange, AMQShortString routingKey, AMQShortString replyText, int replyCode)
{
- super(channelId,-1,null,exchange,routingKey,false);
+ super(-1,0,exchange,routingKey,false);
_replyText = replyText;
_replyCode = replyCode;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage.java
index 17efd7e24f..713c87260c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage.java
@@ -20,23 +20,7 @@
*/
package org.apache.qpid.client.message;
-import java.util.List;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.AMQChannelException;
-import org.apache.qpid.AMQConnectionException;
-import org.apache.qpid.AMQException;
import org.apache.qpid.client.BasicMessageConsumer;
-import org.apache.qpid.framing.AMQFrame;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.BasicDeliverBody;
-import org.apache.qpid.framing.BasicReturnBody;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.MethodDispatcher;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
/**
@@ -46,65 +30,24 @@ import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
* Note that the actual work of creating a JMS message for the client code's use is done outside of the MINA dispatcher
* thread in order to minimise the amount of work done in the MINA dispatcher thread.
*/
-public abstract class UnprocessedMessage<H,B>
+public abstract class UnprocessedMessage
{
- private final int _channelId;
- private final long _deliveryId;
- private final AMQShortString _consumerTag;
- protected AMQShortString _exchange;
- protected AMQShortString _routingKey;
- protected boolean _redelivered;
+ private final int _consumerTag;
+
- public UnprocessedMessage(int channelId,long deliveryId,AMQShortString consumerTag,AMQShortString exchange,AMQShortString routingKey,boolean redelivered)
+ public UnprocessedMessage(int consumerTag)
{
- _channelId = channelId;
- _deliveryId = deliveryId;
_consumerTag = consumerTag;
- _exchange = exchange;
- _routingKey = routingKey;
- _redelivered = redelivered;
}
- public abstract void receiveBody(B nativeMessageBody);
- public abstract void setContentHeader(H nativeMessageHeader);
-
- public int getChannelId()
- {
- return _channelId;
- }
+ abstract public long getDeliveryTag();
- public long getDeliveryTag()
- {
- return _deliveryId;
- }
- public AMQShortString getConsumerTag()
+ public int getConsumerTag()
{
return _consumerTag;
}
- public AMQShortString getExchange()
- {
- return _exchange;
- }
-
- public AMQShortString getRoutingKey()
- {
- return _routingKey;
- }
- public boolean isRedelivered()
- {
- return _redelivered;
- }
- public abstract List<B> getBodies();
-
- public abstract H getContentHeader();
-
- // specific to 0_10
- public String getReplyToURL()
- {
- return "";
- }
-}
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_10.java b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_10.java
index 09f41a9ba6..6b1301a33f 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_10.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_10.java
@@ -20,13 +20,7 @@
*/
package org.apache.qpid.client.message;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.Struct;
+import org.apache.qpid.transport.MessageTransfer;
/**
* This class contains everything needed to process a JMS message. It assembles the deliver body, the content header and
@@ -35,58 +29,25 @@ import org.apache.qpidity.transport.Struct;
* Note that the actual work of creating a JMS message for the client code's use is done outside of the MINA dispatcher
* thread in order to minimise the amount of work done in the MINA dispatcher thread.
*/
-public class UnprocessedMessage_0_10 extends UnprocessedMessage<Struct[],ByteBuffer>
+public class UnprocessedMessage_0_10 extends UnprocessedMessage
{
- private Struct[] _headers;
- private String _replyToURL;
-
- /** List of ContentBody instances. Due to fragmentation you don't know how big this will be in general */
- private List<ByteBuffer> _bodies = new ArrayList<ByteBuffer>();
-
- public UnprocessedMessage_0_10(int channelId,long deliveryId,AMQShortString consumerTag,AMQShortString exchange,AMQShortString routingKey,boolean redelivered)
- {
- super(channelId,deliveryId,consumerTag,exchange,routingKey,redelivered);
- }
-
- public void receiveBody(ByteBuffer body)
- {
-
- _bodies.add(body);
- }
-
- public void setContentHeader(Struct[] headers)
- {
- this._headers = headers;
- for(Struct s: headers)
- {
- if (s instanceof DeliveryProperties)
- {
- DeliveryProperties props = (DeliveryProperties)s;
- _exchange = new AMQShortString(props.getExchange());
- _routingKey = new AMQShortString(props.getRoutingKey());
- _redelivered = props.getRedelivered();
- }
- }
- }
+ private MessageTransfer _transfer;
- public Struct[] getContentHeader()
+ public UnprocessedMessage_0_10(int consumerTag, MessageTransfer xfr)
{
- return _headers;
- }
-
- public List<ByteBuffer> getBodies()
- {
- return _bodies;
+ super(consumerTag);
+ _transfer = xfr;
}
// additional 0_10 method
- public String getReplyToURL()
+
+ public long getDeliveryTag()
{
- return _replyToURL;
+ return _transfer.getId();
}
- public void setReplyToURL(String url)
+ public MessageTransfer getMessageTransfer()
{
- _replyToURL = url;
+ return _transfer;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
index 78da8cdca2..685e646d85 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/UnprocessedMessage_0_8.java
@@ -26,7 +26,6 @@ import java.util.List;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicDeliverBody;
-import org.apache.qpid.framing.BasicReturnBody;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
@@ -37,32 +36,54 @@ import org.apache.qpid.framing.ContentHeaderBody;
* Note that the actual work of creating a JMS message for the client code's use is done outside of the MINA dispatcher
* thread in order to minimise the amount of work done in the MINA dispatcher thread.
*/
-public class UnprocessedMessage_0_8 extends UnprocessedMessage<ContentHeaderBody,ContentBody>
+public class UnprocessedMessage_0_8 extends UnprocessedMessage
{
private long _bytesReceived = 0;
+
+ private AMQShortString _exchange;
+ private AMQShortString _routingKey;
+ private final long _deliveryId;
+ protected boolean _redelivered;
+
private BasicDeliverBody _deliverBody;
private ContentHeaderBody _contentHeader;
/** List of ContentBody instances. Due to fragmentation you don't know how big this will be in general */
private List<ContentBody> _bodies;
- public UnprocessedMessage_0_8(int channelId,long deliveryId,AMQShortString consumerTag,AMQShortString exchange,AMQShortString routingKey,boolean redelivered)
+ public UnprocessedMessage_0_8(long deliveryId, int consumerTag, AMQShortString exchange, AMQShortString routingKey, boolean redelivered)
+ {
+ super(consumerTag);
+ _exchange = exchange;
+ _routingKey = routingKey;
+
+ _redelivered = redelivered;
+ _deliveryId = deliveryId;
+ }
+
+
+ public AMQShortString getExchange()
+ {
+ return _exchange;
+ }
+
+ public AMQShortString getRoutingKey()
{
- super(channelId,deliveryId,consumerTag,exchange,routingKey,redelivered);
+ return _routingKey;
}
- public UnprocessedMessage_0_8(int channelId, BasicReturnBody body)
+ public long getDeliveryTag()
{
- //FIXME: TGM, SRSLY 4RL
- super(channelId, 0, null, body.getExchange(), body.getRoutingKey(), false);
+ return _deliveryId;
}
- public UnprocessedMessage_0_8(int channelId, BasicDeliverBody body)
+ public boolean isRedelivered()
{
- super(channelId, body.getDeliveryTag(), body.getConsumerTag(), body.getExchange(), body.getRoutingKey(), false);
+ return _redelivered;
}
+
public void receiveBody(ContentBody body)
{
@@ -124,7 +145,7 @@ public class UnprocessedMessage_0_8 extends UnprocessedMessage<ContentHeaderBody
public String toString()
{
StringBuilder buf = new StringBuilder();
- buf.append("Channel Id : " + this.getChannelId());
+
if (_contentHeader != null)
{
buf.append("ContentHeader " + _contentHeader);
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java
new file mode 100644
index 0000000000..1de0e7bdfc
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQIoTransportProtocolSession.java
@@ -0,0 +1,125 @@
+package org.apache.qpid.client.protocol;
+
+import java.util.UUID;
+
+import javax.security.sasl.SaslClient;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.mina.common.IdleStatus;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.ConnectionTuneParameters;
+import org.apache.qpid.client.handler.ClientMethodDispatcherImpl;
+import org.apache.qpid.client.state.AMQState;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ProtocolInitiation;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.transport.Sender;
+
+public class AMQIoTransportProtocolSession extends AMQProtocolSession
+{
+
+ protected Sender<java.nio.ByteBuffer> _ioSender;
+ private SaslClient _saslClient;
+ private ConnectionTuneParameters _connectionTuneParameters;
+
+ public AMQIoTransportProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection)
+ {
+ super(protocolHandler, connection);
+ }
+
+ @Override
+ public void closeProtocolSession(boolean waitLast) throws AMQException
+ {
+ _ioSender.close();
+ _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_CLOSED);
+ }
+
+ @Override
+ public void init()
+ {
+ _ioSender.send(new ProtocolInitiation(_connection.getProtocolVersion()).toNioByteBuffer());
+ _ioSender.flush();
+ }
+
+ @Override
+ protected AMQShortString generateQueueName()
+ {
+ int id;
+ synchronized (_queueIdLock)
+ {
+ id = _queueId++;
+ }
+ return new AMQShortString("tmp_" + UUID.randomUUID() + "_" + id);
+ }
+
+ @Override
+ public AMQConnection getAMQConnection()
+ {
+ return _connection;
+ }
+
+ @Override
+ public SaslClient getSaslClient()
+ {
+ return _saslClient;
+ }
+
+ @Override
+ public void setSaslClient(SaslClient client)
+ {
+ _saslClient = client;
+ }
+
+ /** @param delay delay in seconds (not ms) */
+ @Override
+ void initHeartbeats(int delay)
+ {
+ if (delay > 0)
+ {
+ // FIXME: actually do something here
+ HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay));
+ }
+ }
+
+ @Override
+ public void methodFrameReceived(final int channel, final AMQMethodBody amqMethodBody) throws AMQException
+ {
+ // FIXME?
+ _protocolHandler.methodBodyReceived(channel, amqMethodBody, null);
+ }
+
+ @Override
+ public void writeFrame(AMQDataBlock frame, boolean wait)
+ {
+ _ioSender.send(frame.toNioByteBuffer());
+ if (wait)
+ {
+ _ioSender.flush();
+ }
+ }
+
+ @Override
+ public void setSender(Sender<java.nio.ByteBuffer> sender)
+ {
+ _ioSender = sender;
+ }
+
+ @Override
+ public ConnectionTuneParameters getConnectionTuneParameters()
+ {
+ return _connectionTuneParameters;
+ }
+
+ @Override
+ public void setConnectionTuneParameters(ConnectionTuneParameters params)
+ {
+ _connectionTuneParameters = params;
+ AMQConnection con = getAMQConnection();
+ con.setMaximumChannelCount(params.getChannelMax());
+ con.setMaximumFrameSize(params.getFrameMax());
+ initHeartbeats((int) params.getHeartbeat());
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index 2d8074eea2..e92817f713 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -43,14 +43,17 @@ import org.apache.qpid.client.failover.FailoverHandler;
import org.apache.qpid.client.failover.FailoverState;
import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.StateWaiter;
import org.apache.qpid.client.state.listener.SpecificMethodFrameListener;
import org.apache.qpid.codec.AMQCodecFactory;
import org.apache.qpid.framing.*;
+import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.pool.ReadWriteThreadModel;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.network.io.IoTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,28 +103,29 @@ import java.util.concurrent.CountDownLatch;
* <p/><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
* <tr><td> Create the filter chain to filter this handlers events.
- * <td> {@link ProtocolCodecFilter}, {@link SSLContextFactory}, {@link SSLFilter}, {@link ReadWriteThreadModel}.
+ * <td> {@link ProtocolCodecFilter}, {@link SSLContextFactory}, {@link SSLFilter}, {@link ReadWriteThreadModel}.
*
* <tr><td> Maintain fail-over state.
* <tr><td>
* </table>
*
* @todo Explain the system property: amqj.shared_read_write_pool. How does putting the protocol codec filter before the
- * async write filter make it a shared pool? The pooling filter uses the same thread pool for reading and writing
- * anyway, see {@link org.apache.qpid.pool.PoolingFilter}, docs for comments. Will putting the protocol codec
- * filter before it mean not doing the read/write asynchronously but in the main filter thread?
- *
+ * async write filter make it a shared pool? The pooling filter uses the same thread pool for reading and writing
+ * anyway, see {@link org.apache.qpid.pool.PoolingFilter}, docs for comments. Will putting the protocol codec
+ * filter before it mean not doing the read/write asynchronously but in the main filter thread?
* @todo Use a single handler instance, by shifting everything to do with the 'protocol session' state, including
- * failover state, into AMQProtocolSession, and tracking that from AMQConnection? The lifecycles of
- * AMQProtocolSesssion and AMQConnection will be the same, so if there is high cohesion between them, they could
- * be merged, although there is sense in keeping the session model seperate. Will clarify things by having data
- * held per protocol handler, per protocol session, per network connection, per channel, in seperate classes, so
- * that lifecycles of the fields match lifecycles of their containing objects.
+ * failover state, into AMQProtocolSession, and tracking that from AMQConnection? The lifecycles of
+ * AMQProtocolSesssion and AMQConnection will be the same, so if there is high cohesion between them, they could
+ * be merged, although there is sense in keeping the session model seperate. Will clarify things by having data
+ * held per protocol handler, per protocol session, per network connection, per channel, in seperate classes, so
+ * that lifecycles of the fields match lifecycles of their containing objects.
*/
public class AMQProtocolHandler extends IoHandlerAdapter
{
/** Used for debugging. */
private static final Logger _logger = LoggerFactory.getLogger(AMQProtocolHandler.class);
+ private static final Logger _protocolLogger = LoggerFactory.getLogger("qpid.protocol");
+ private static final boolean PROTOCOL_DEBUG = (System.getProperty("amqj.protocol.logging.level") != null);
/**
* The connection that this protocol handler is associated with. There is a 1-1 mapping between connection
@@ -136,7 +140,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
private AMQStateManager _stateManager = new AMQStateManager();
/** Holds the method listeners, */
- private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet();
+ private final CopyOnWriteArraySet<AMQMethodListener> _frameListeners = new CopyOnWriteArraySet<AMQMethodListener>();
/**
* We create the failover handler when the session is created since it needs a reference to the IoSession in order
@@ -154,14 +158,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter
/** Used to provide a condition to wait upon for operations that are required to wait for failover to complete. */
private CountDownLatch _failoverLatch;
-
/** The last failover exception that occured */
private FailoverException _lastFailoverException;
/** Defines the default timeout to use for synchronous protocol commands. */
private final long DEFAULT_SYNC_TIMEOUT = 1000 * 30;
-
/**
* Creates a new protocol handler, associated with the specified client connection instance.
*
@@ -245,11 +247,27 @@ public class AMQProtocolHandler extends IoHandlerAdapter
_logger.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage());
}
}
- _protocolSession = new AMQProtocolSession(this, session, _connection, getStateManager());
+ _protocolSession = new AMQProtocolSession(this, session, _connection);
+
+ _stateManager.setProtocolSession(_protocolSession);
+
_protocolSession.init();
}
/**
+ * Called when we want to create a new IoTransport session
+ * @param brokerDetail
+ */
+ public void createIoTransportSession(BrokerDetails brokerDetail)
+ {
+ _protocolSession = new AMQProtocolSession(this, _connection);
+ _stateManager.setProtocolSession(_protocolSession);
+ IoTransport.connect_0_9(getProtocolSession(),
+ brokerDetail.getHost(), brokerDetail.getPort());
+ _protocolSession.init();
+ }
+
+ /**
* Called when the network connection is closed. This can happen, either because the client explicitly requested
* that the connection be closed, in which case nothing is done, or because the connection died. In the case
* where the connection died, an attempt to failover automatically to a new connection may be started. The failover
@@ -263,7 +281,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
* @param session The MINA session.
*
* @todo Clarify: presumably exceptionCaught is called when the client is sending during a connection failure and
- * not otherwise? The above comment doesn't make that clear.
+ * not otherwise? The above comment doesn't make that clear.
*/
public void sessionClosed(IoSession session)
{
@@ -374,7 +392,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
"cause isn't AMQConnectionClosedException: " + cause, cause);
AMQException amqe = new AMQException("Protocol handler error: " + cause, cause);
- propagateExceptionToWaiters(amqe);
+ propagateExceptionToAllWaiters(amqe);
}
_connection.exceptionReceived(cause);
@@ -395,7 +413,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
// we notify the state manager of the error in case we have any clients waiting on a state
// change. Those "waiters" will be interrupted and can handle the exception
AMQException amqe = new AMQException("Protocol handler error: " + cause, cause);
- propagateExceptionToWaiters(amqe);
+ propagateExceptionToAllWaiters(amqe);
_connection.exceptionReceived(cause);
}
}
@@ -405,11 +423,33 @@ public class AMQProtocolHandler extends IoHandlerAdapter
* These are for the state manager (waiting for a state change) or a frame listener (waiting for a particular type
* of frame to arrive). When an error occurs we need to notify these waiters so that they can react appropriately.
*
+ * This should be called only when the exception is fatal for the connection.
+ *
* @param e the exception to propagate
+ *
+ * @see #propagateExceptionToFrameListeners
+ * @see #propagateExceptionToStateWaiters
*/
- public void propagateExceptionToWaiters(Exception e)
+ public void propagateExceptionToAllWaiters(Exception e)
+ {
+ propagateExceptionToFrameListeners(e);
+ propagateExceptionToStateWaiters(e);
+ }
+
+ /**
+ * This caters for the case where we only need to propogate an exception to the the frame listeners to interupt any
+ * protocol level waits.
+ *
+ * This will would normally be used to notify all Frame Listeners that Failover is about to occur and they should
+ * stop waiting and relinquish the Failover lock {@see FailoverHandler}.
+ *
+ * Once the {@link FailoverHandler} has re-established the connection then the listeners will be able to re-attempt
+ * their protocol request and so listen again for the correct frame.
+ *
+ * @param e the exception to propagate
+ */
+ public void propagateExceptionToFrameListeners(Exception e)
{
-
if (!_frameListeners.isEmpty())
{
final Iterator it = _frameListeners.iterator();
@@ -421,6 +461,22 @@ public class AMQProtocolHandler extends IoHandlerAdapter
}
}
+ /**
+ * This caters for the case where we only need to propogate an exception to the the state manager to interupt any
+ * thing waiting for a state change.
+ *
+ * Currently (2008-07-15) the state manager is only used during 0-8/0-9 Connection establishement.
+ *
+ * Normally the state manager would not need to be notified without notifiying the frame listeners so in normal
+ * cases {@link #propagateExceptionToAllWaiters} would be the correct choice.
+ *
+ * @param e the exception to propagate
+ */
+ public void propagateExceptionToStateWaiters(Exception e)
+ {
+ getStateManager().error(e);
+ }
+
public void notifyFailoverStarting()
{
// Set the last exception in the sync block to ensure the ordering with add.
@@ -431,7 +487,9 @@ public class AMQProtocolHandler extends IoHandlerAdapter
_lastFailoverException = new FailoverException("Failing over about to start");
}
- propagateExceptionToWaiters(_lastFailoverException);
+ //Only notify the Frame listeners that failover is going to occur as the State listeners shouldn't be
+ // interupted unless failover cannot restore the state.
+ propagateExceptionToFrameListeners(_lastFailoverException);
}
public void failoverInProgress()
@@ -443,6 +501,11 @@ public class AMQProtocolHandler extends IoHandlerAdapter
public void messageReceived(IoSession session, Object message) throws Exception
{
+ if (PROTOCOL_DEBUG)
+ {
+ _protocolLogger.info(String.format("RECV: [%s] %s", this, message));
+ }
+
if(message instanceof AMQFrame)
{
final boolean debug = _logger.isDebugEnabled();
@@ -459,7 +522,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody);
- bodyFrame.handle(frame.getChannel(),_protocolSession);
+ bodyFrame.handle(frame.getChannel(), _protocolSession);
_connection.bytesReceived(_protocolSession.getIoSession().getReadBytes());
}
@@ -508,20 +571,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter
if (!wasAnyoneInterested)
{
throw new AMQException(null, "AMQMethodEvent " + evt + " was not processed by any listener. Listeners:"
- + _frameListeners, null);
+ + _frameListeners, null);
}
}
catch (AMQException e)
- {
- if (!_frameListeners.isEmpty())
- {
- Iterator it = _frameListeners.iterator();
- while (it.hasNext())
- {
- final AMQMethodListener listener = (AMQMethodListener) it.next();
- listener.error(e);
- }
- }
+ {
+ propagateExceptionToFrameListeners(e);
exceptionCaught(session, e);
}
@@ -532,6 +587,11 @@ public class AMQProtocolHandler extends IoHandlerAdapter
public void messageSent(IoSession session, Object message) throws Exception
{
+ if (PROTOCOL_DEBUG)
+ {
+ _protocolLogger.debug(String.format("SEND: [%s] %s", this, message));
+ }
+
final long sentMessages = _messagesOut++;
final boolean debug = _logger.isDebugEnabled();
@@ -542,34 +602,13 @@ public class AMQProtocolHandler extends IoHandlerAdapter
}
_connection.bytesSent(session.getWrittenBytes());
- if (debug)
- {
- _logger.debug("Sent frame " + message);
- }
- }
-
- /*
- public void addFrameListener(AMQMethodListener listener)
- {
- _frameListeners.add(listener);
- }
-
- public void removeFrameListener(AMQMethodListener listener)
- {
- _frameListeners.remove(listener);
- }
- */
- public void attainState(AMQState s) throws AMQException
- {
- getStateManager().attainState(s);
}
- public AMQState attainState(Set<AMQState> states) throws AMQException
+ public StateWaiter createWaiter(Set<AMQState> states) throws AMQException
{
- return getStateManager().attainState(states);
+ return getStateManager().createWaiter(states);
}
-
/**
* Convenience method that writes a frame to the protocol session. Equivalent to calling
* getProtocolSession().write().
@@ -617,14 +656,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter
{
throw _lastFailoverException;
}
-
+
_frameListeners.add(listener);
}
_protocolSession.writeFrame(frame);
- AMQMethodEvent e = listener.blockForFrame(timeout);
-
- return e;
+ return listener.blockForFrame(timeout);
// When control resumes before this line, a reply will have been received
// that matches the criteria defined in the blocking listener
}
@@ -669,8 +706,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
getStateManager().changeState(AMQState.CONNECTION_CLOSING);
ConnectionCloseBody body = _protocolSession.getMethodRegistry().createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
- new AMQShortString("JMS client is closing the connection."),0,0);
-
+ new AMQShortString("JMS client is closing the connection."), 0, 0);
final AMQFrame frame = body.generateFrame(0);
@@ -745,10 +781,6 @@ public class AMQProtocolHandler extends IoHandlerAdapter
public void setStateManager(AMQStateManager stateManager)
{
_stateManager = stateManager;
- if (_protocolSession != null)
- {
- _protocolSession.setStateManager(stateManager);
- }
}
public AMQProtocolSession getProtocolSession()
@@ -778,7 +810,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter
public MethodRegistry getMethodRegistry()
{
- return getStateManager().getMethodRegistry();
+ return _protocolSession.getMethodRegistry();
}
public ProtocolVersion getProtocolVersion()
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
index 6e782e0bfc..5e12a5e6f8 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
@@ -30,7 +30,6 @@ import org.slf4j.LoggerFactory;
import javax.jms.JMSException;
import javax.security.sasl.SaslClient;
-import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -38,13 +37,14 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.ConnectionTuneParameters;
-import org.apache.qpid.client.message.ReturnMessage;
import org.apache.qpid.client.message.UnprocessedMessage;
import org.apache.qpid.client.message.UnprocessedMessage_0_8;
import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.framing.*;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.Sender;
import org.apache.qpid.client.handler.ClientMethodDispatcherImpl;
/**
@@ -67,8 +67,6 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
protected final IoSession _minaProtocolSession;
- private AMQStateManager _stateManager;
-
protected WriteFuture _lastWriteFuture;
/**
@@ -86,7 +84,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
* Maps from a channel id to an unprocessed message. This is used to tie together the JmsDeliverBody (which arrives
* first) with the subsequent content header and content bodies.
*/
- private final ConcurrentMap<Integer,UnprocessedMessage> _channelId2UnprocessedMsgMap = new ConcurrentHashMap<Integer,UnprocessedMessage>();
+ private final ConcurrentMap<Integer, UnprocessedMessage> _channelId2UnprocessedMsgMap = new ConcurrentHashMap<Integer, UnprocessedMessage>();
private final UnprocessedMessage[] _channelId2UnprocessedMsgArray = new UnprocessedMessage[16];
/** Counter to ensure unique queue names */
@@ -97,26 +95,17 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
// private VersionSpecificRegistry _registry =
// MainRegistry.getVersionSpecificRegistry(ProtocolVersion.getLatestSupportedVersion());
-
private MethodRegistry _methodRegistry =
MethodRegistry.getMethodRegistry(ProtocolVersion.getLatestSupportedVersion());
-
private MethodDispatcher _methodDispatcher;
+ protected final AMQConnection _connection;
- private final AMQConnection _connection;
private static final int FAST_CHANNEL_ACCESS_MASK = 0xFFFFFFF0;
public AMQProtocolSession(AMQProtocolHandler protocolHandler, IoSession protocolSession, AMQConnection connection)
{
- this(protocolHandler, protocolSession, connection, new AMQStateManager());
-
- }
-
- public AMQProtocolSession(AMQProtocolHandler protocolHandler, IoSession protocolSession, AMQConnection connection,
- AMQStateManager stateManager)
- {
_protocolHandler = protocolHandler;
_minaProtocolSession = protocolSession;
_minaProtocolSession.setAttachment(this);
@@ -124,20 +113,27 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
_minaProtocolSession.setAttribute(AMQ_CONNECTION, connection);
// fixme - real value needed
_minaProtocolSession.setWriteTimeout(LAST_WRITE_FUTURE_JOIN_TIMEOUT);
- _stateManager = stateManager;
- _stateManager.setProtocolSession(this);
_protocolVersion = connection.getProtocolVersion();
_methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(ProtocolVersion.getLatestSupportedVersion(),
- stateManager);
+ this);
_connection = connection;
}
+ public AMQProtocolSession(AMQProtocolHandler protocolHandler, AMQConnection connection)
+ {
+ _protocolHandler = protocolHandler;
+ _minaProtocolSession = null;
+ _protocolVersion = connection.getProtocolVersion();
+ _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(ProtocolVersion.getLatestSupportedVersion(),
+ this);
+ _connection = connection;
+ }
+
public void init()
{
// start the process of setting up the connection. This is the first place that
// data is written to the server.
-
_minaProtocolSession.write(new ProtocolInitiation(_connection.getProtocolVersion()));
}
@@ -161,14 +157,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public AMQStateManager getStateManager()
{
- return _stateManager;
- }
-
- public void setStateManager(AMQStateManager stateManager)
- {
- _stateManager = stateManager;
- _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(_protocolVersion,
- stateManager);
+ return _protocolHandler.getStateManager();
}
public String getVirtualHost()
@@ -193,7 +182,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public SaslClient getSaslClient()
{
- return (SaslClient) _minaProtocolSession.getAttribute(SASL_CLIENT);
+ return (SaslClient) _minaProtocolSession.getAttribute(SASL_CLIENT);
}
/**
@@ -235,12 +224,11 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
*
* @throws AMQException if this was not expected
*/
- public void unprocessedMessageReceived(UnprocessedMessage message) throws AMQException
- {
- final int channelId = message.getChannelId();
- if((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
+ public void unprocessedMessageReceived(final int channelId, UnprocessedMessage message) throws AMQException
+ {
+ if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
- _channelId2UnprocessedMsgArray[channelId] = message;
+ _channelId2UnprocessedMsgArray[channelId] = message;
}
else
{
@@ -250,18 +238,17 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
public void contentHeaderReceived(int channelId, ContentHeaderBody contentHeader) throws AMQException
{
- final UnprocessedMessage msg = (channelId & FAST_CHANNEL_ACCESS_MASK) == 0 ? _channelId2UnprocessedMsgArray[channelId]
- : _channelId2UnprocessedMsgMap.get(channelId);
-
+ final UnprocessedMessage_0_8 msg = (UnprocessedMessage_0_8) ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0 ? _channelId2UnprocessedMsgArray[channelId]
+ : _channelId2UnprocessedMsgMap.get(channelId));
if (msg == null)
{
- throw new AMQException(null, "Error: received content header without having received a BasicDeliver frame first", null);
+ throw new AMQException(null, "Error: received content header without having received a BasicDeliver frame first on session:" + this, null);
}
if (msg.getContentHeader() != null)
{
- throw new AMQException(null, "Error: received duplicate content header or did not receive correct number of content body frames", null);
+ throw new AMQException(null, "Error: received duplicate content header or did not receive correct number of content body frames on session:" + this, null);
}
msg.setContentHeader(contentHeader);
@@ -275,7 +262,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
{
UnprocessedMessage_0_8 msg;
final boolean fastAccess = (channelId & FAST_CHANNEL_ACCESS_MASK) == 0;
- if(fastAccess)
+ if (fastAccess)
{
msg = (UnprocessedMessage_0_8) _channelId2UnprocessedMsgArray[channelId];
}
@@ -291,7 +278,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
if (msg.getContentHeader() == null)
{
- if(fastAccess)
+ if (fastAccess)
{
_channelId2UnprocessedMsgArray[channelId] = null;
}
@@ -302,15 +289,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
throw new AMQException(null, "Error: received content body without having received a ContentHeader frame first", null);
}
- /*try
- {*/
msg.receiveBody(contentBody);
- /*}
- catch (UnexpectedBodyReceivedException e)
- {
- _channelId2UnprocessedMsgMap.remove(channelId);
- throw e;
- }*/
if (msg.isAllBodyDataReceived())
{
@@ -333,7 +312,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
{
AMQSession session = getSession(channelId);
session.messageReceived(msg);
- if((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
+ if ((channelId & FAST_CHANNEL_ACCESS_MASK) == 0)
{
_channelId2UnprocessedMsgArray[channelId] = null;
}
@@ -431,12 +410,12 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
return (AMQConnection) _minaProtocolSession.getAttribute(AMQ_CONNECTION);
}
- public void closeProtocolSession()
+ public void closeProtocolSession() throws AMQException
{
closeProtocolSession(true);
}
- public void closeProtocolSession(boolean waitLast)
+ public void closeProtocolSession(boolean waitLast) throws AMQException
{
_logger.debug("Waiting for last write to join.");
if (waitLast && (_lastWriteFuture != null))
@@ -445,7 +424,15 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
}
_logger.debug("Closing protocol session");
+
final CloseFuture future = _minaProtocolSession.close();
+
+ // There is no recovery we can do if the join on the close failes so simply mark the connection CLOSED
+ // then wait for the connection to close.
+ // ritchiem: Could this release BlockingWaiters to early? The close has been done as much as possible so any
+ // error now shouldn't matter.
+
+ _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_CLOSED);
future.join(LAST_WRITE_FUTURE_JOIN_TIMEOUT);
}
@@ -482,16 +469,16 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
{
final AMQSession session = getSession(channelId);
- session.confirmConsumerCancelled(consumerTag);
+ session.confirmConsumerCancelled(consumerTag.toIntValue());
}
public void setProtocolVersion(final ProtocolVersion pv)
{
_protocolVersion = pv;
_methodRegistry = MethodRegistry.getMethodRegistry(pv);
- _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(pv, _stateManager);
+ _methodDispatcher = ClientMethodDispatcherImpl.newMethodDispatcher(pv, this);
- // _registry = MainRegistry.getVersionSpecificRegistry(versionMajor, versionMinor);
+ // _registry = MainRegistry.getVersionSpecificRegistry(versionMajor, versionMinor);
}
public byte getProtocolMinorVersion()
@@ -524,12 +511,12 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
return _methodDispatcher;
}
-
public void setTicket(int ticket, int channelId)
{
final AMQSession session = getSession(channelId);
session.setTicket(ticket);
}
+
public void setMethodDispatcher(MethodDispatcher methodDispatcher)
{
_methodDispatcher = methodDispatcher;
@@ -545,4 +532,14 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession
{
_protocolHandler.methodBodyReceived(channel, amqMethodBody, _minaProtocolSession);
}
+
+ public void notifyError(Exception error)
+ {
+ _protocolHandler.propagateExceptionToAllWaiters(error);
+ }
+
+ public void setSender(Sender<java.nio.ByteBuffer> sender)
+ {
+ // No-op, interface munging
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java b/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java
index 0ab2e07340..2bc609ebf2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java
+++ b/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java
@@ -20,9 +20,14 @@
*/
package org.apache.qpid.client.protocol;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQTimeoutException;
import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.client.util.BlockingWaiter;
import org.apache.qpid.framing.AMQMethodBody;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
@@ -54,38 +59,17 @@ import org.apache.qpid.protocol.AMQMethodListener;
* </table>
*
* @todo Might be neater if this method listener simply wrapped another that provided the method handling using a
- * methodRecevied method. The processMethod takes an additional channelId, however none of the implementations
- * seem to use it. So wrapping the listeners is possible.
- *
- * @todo What is to stop a blocking method listener, receiving a second method whilst it is registered as a listener,
- * overwriting the first one before the caller of the block method has had a chance to examine it? If one-shot
- * behaviour is to be intended it should be enforced, perhaps by always returning false once the blocked for
- * method has been received.
- *
- * @todo Interuption is caught but not handled. This could be allowed to fall through. This might actually be usefull
- * for fail-over where a thread is blocking when failure happens, it could be interrupted to abandon or retry
- * when this happens. At the very least, restore the interrupted status flag.
- *
+ * methodRecevied method. The processMethod takes an additional channelId, however none of the implementations
+ * seem to use it. So wrapping the listeners is possible.
* @todo If the retrotranslator can handle it, could use a SynchronousQueue to implement this rendezvous. Need to
- * check that SynchronousQueue has a non-blocking put method available.
+ * check that SynchronousQueue has a non-blocking put method available.
*/
-public abstract class BlockingMethodFrameListener implements AMQMethodListener
+public abstract class BlockingMethodFrameListener extends BlockingWaiter<AMQMethodEvent> implements AMQMethodListener
{
- /** This flag is used to indicate that the blocked for method has been received. */
- private volatile boolean _ready = false;
-
- /** Used to protect the shared event and ready flag between the producer and consumer. */
- private final Object _lock = new Object();
-
- /** Used to hold the most recent exception that is passed to the {@link #error(Exception)} method. */
- private volatile Exception _error;
/** Holds the channel id for the channel upon which this listener is waiting for a response. */
protected int _channelId;
- /** Holds the incoming method. */
- protected AMQMethodEvent _doneEvt = null;
-
/**
* Creates a new method listener, that filters incoming method to just those that match the specified channel id.
*
@@ -104,7 +88,14 @@ public abstract class BlockingMethodFrameListener implements AMQMethodListener
*
* @return <tt>true</tt> if the method was handled, <tt>false</tt> otherwise.
*/
- public abstract boolean processMethod(int channelId, AMQMethodBody frame); // throws AMQException;
+ public abstract boolean processMethod(int channelId, AMQMethodBody frame);
+
+ public boolean process(AMQMethodEvent evt)
+ {
+ AMQMethodBody method = evt.getMethod();
+
+ return (evt.getChannelId() == _channelId) && processMethod(evt.getChannelId(), method);
+ }
/**
* Informs this listener that an AMQP method has been received.
@@ -113,37 +104,9 @@ public abstract class BlockingMethodFrameListener implements AMQMethodListener
*
* @return <tt>true</tt> if this listener has handled the method, <tt>false</tt> otherwise.
*/
- public boolean methodReceived(AMQMethodEvent evt) // throws AMQException
+ public boolean methodReceived(AMQMethodEvent evt)
{
- AMQMethodBody method = evt.getMethod();
-
- /*try
- {*/
- boolean ready = (evt.getChannelId() == _channelId) && processMethod(evt.getChannelId(), method);
-
- if (ready)
- {
- // we only update the flag from inside the synchronized block
- // so that the blockForFrame method cannot "miss" an update - it
- // will only ever read the flag from within the synchronized block
- synchronized (_lock)
- {
- _doneEvt = evt;
- _ready = ready;
- _lock.notify();
- }
- }
-
- return ready;
-
- /*}
- catch (AMQException e)
- {
- error(e);
- // we rethrow the error here, and the code in the frame dispatcher will go round
- // each listener informing them that an exception has been thrown
- throw e;
- }*/
+ return received(evt);
}
/**
@@ -159,75 +122,15 @@ public abstract class BlockingMethodFrameListener implements AMQMethodListener
*/
public AMQMethodEvent blockForFrame(long timeout) throws AMQException, FailoverException
{
- synchronized (_lock)
+ try
{
- while (!_ready)
- {
- try
- {
- if (timeout == -1)
- {
- _lock.wait();
- }
- else
- {
-
- _lock.wait(timeout);
- if (!_ready)
- {
- _error = new AMQTimeoutException("Server did not respond in a timely fashion", null);
- _ready = true;
- }
- }
- }
- catch (InterruptedException e)
- {
- // IGNORE -- //fixme this isn't ideal as being interrupted isn't equivellant to sucess
- // if (!_ready && timeout != -1)
- // {
- // _error = new AMQException("Server did not respond timely");
- // _ready = true;
- // }
- }
- }
+ return (AMQMethodEvent) block(timeout);
}
-
- if (_error != null)
+ finally
{
- if (_error instanceof AMQException)
- {
- throw (AMQException) _error;
- }
- else if (_error instanceof FailoverException)
- {
- // This should ensure that FailoverException is not wrapped and can be caught.
- throw (FailoverException) _error; // needed to expose FailoverException.
- }
- else
- {
- throw new AMQException(null, "Woken up due to " + _error.getClass(), _error);
- }
+ //Prevent any more errors being notified to this waiter.
+ close();
}
-
- return _doneEvt;
}
- /**
- * This is a callback, called by the MINA dispatcher thread only. It is also called from within this
- * class to avoid code repetition but again is only called by the MINA dispatcher thread.
- *
- * @param e
- */
- public void error(Exception e)
- {
- // set the error so that the thread that is blocking (against blockForFrame())
- // can pick up the exception and rethrow to the caller
- _error = e;
-
- synchronized (_lock)
- {
- _ready = true;
- _lock.notify();
- }
- }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
index eda1a1f5fd..f8645139f2 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
@@ -28,15 +28,28 @@ import org.apache.qpid.protocol.AMQMethodListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Iterator;
import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
- * The state manager is responsible for managing the state of the protocol session. <p/> For each AMQProtocolHandler
- * there is a separate state manager.
+ * The state manager is responsible for managing the state of the protocol session. <p/>
+ * For each {@link org.apache.qpid.client.protocol.AMQProtocolHandler} there is a separate state manager.
+ *
+ * The AMQStateManager is now attached to the {@link org.apache.qpid.client.protocol.AMQProtocolHandler} and that is the sole point of reference so that
+ * As the {@link AMQProtocolSession} changes due to failover the AMQStateManager need not be copied around.
+ *
+ * The StateManager works by any component can wait for a state change to occur by using the following sequence.
+ *
+ * <li>StateWaiter waiter = stateManager.createWaiter(Set<AMQState> states);
+ * <li> // Perform action that will cause state change
+ * <li>waiter.await();
+ *
+ * The two step process is required as there is an inherit race condition between starting a process that will cause
+ * the state to change and then attempting to wait for that change. The interest in the change must be first set up so
+ * that any asynchrous errors that occur can be delivered to the correct waiters.
*/
-public class AMQStateManager
+public class AMQStateManager implements AMQMethodListener
{
private static final Logger _logger = LoggerFactory.getLogger(AMQStateManager.class);
@@ -45,16 +58,13 @@ public class AMQStateManager
/** The current state */
private AMQState _currentState;
-
- /**
- * Maps from an AMQState instance to a Map from Class to StateTransitionHandler. The class must be a subclass of
- * AMQFrame.
- */
-
-
private final Object _stateLock = new Object();
+
private static final long MAXIMUM_STATE_WAIT_TIME = Long.parseLong(System.getProperty("amqj.MaximumStateWait", "30000"));
+ protected final List<StateWaiter> _waiters = new CopyOnWriteArrayList<StateWaiter>();
+ private Exception _lastException;
+
public AMQStateManager()
{
this(null);
@@ -62,18 +72,15 @@ public class AMQStateManager
public AMQStateManager(AMQProtocolSession protocolSession)
{
- this(AMQState.CONNECTION_NOT_STARTED, true, protocolSession);
+ this(AMQState.CONNECTION_NOT_STARTED, protocolSession);
}
- protected AMQStateManager(AMQState state, boolean register, AMQProtocolSession protocolSession)
+ protected AMQStateManager(AMQState state, AMQProtocolSession protocolSession)
{
_protocolSession = protocolSession;
_currentState = state;
-
}
-
-
public AMQState getCurrentState()
{
return _currentState;
@@ -86,107 +93,107 @@ public class AMQStateManager
synchronized (_stateLock)
{
_currentState = newState;
- _stateLock.notifyAll();
+
+ _logger.debug("Notififying State change to " + _waiters.size() + " : " + _waiters);
+
+ for (StateWaiter waiter : _waiters)
+ {
+ waiter.received(newState);
+ }
}
}
-
public <B extends AMQMethodBody> boolean methodReceived(AMQMethodEvent<B> evt) throws AMQException
{
-
B method = evt.getMethod();
-
+
// StateAwareMethodListener handler = findStateTransitionHandler(_currentState, evt.getMethod());
method.execute(_protocolSession.getMethodDispatcher(), evt.getChannelId());
return true;
}
-
- public void attainState(final AMQState s) throws AMQException
+ /**
+ * Setting of the ProtocolSession will be required when Failover has been successfuly compeleted.
+ *
+ * The new {@link AMQProtocolSession} that has been re-established needs to be provided as that is now the
+ * connection to the network.
+ *
+ * @param session The new protocol session
+ */
+ public void setProtocolSession(AMQProtocolSession session)
{
- synchronized (_stateLock)
+ if (_logger.isInfoEnabled())
{
- final long waitUntilTime = System.currentTimeMillis() + MAXIMUM_STATE_WAIT_TIME;
- long waitTime = MAXIMUM_STATE_WAIT_TIME;
-
- while ((_currentState != s) && (waitTime > 0))
- {
- try
- {
- _stateLock.wait(MAXIMUM_STATE_WAIT_TIME);
- }
- catch (InterruptedException e)
- {
- _logger.warn("Thread interrupted");
- }
-
- if (_currentState != s)
- {
- waitTime = waitUntilTime - System.currentTimeMillis();
- }
- }
-
- if (_currentState != s)
- {
- _logger.warn("State not achieved within permitted time. Current state " + _currentState
- + ", desired state: " + s);
- throw new AMQException(null, "State not achieved within permitted time. Current state " + _currentState
- + ", desired state: " + s, null);
- }
+ _logger.info("Setting ProtocolSession:" + session);
}
-
- // at this point the state will have changed.
+ _protocolSession = session;
}
- public AMQProtocolSession getProtocolSession()
+ /**
+ * Propogate error to waiters
+ *
+ * @param error The error to propogate.
+ */
+ public void error(Exception error)
{
- return _protocolSession;
+ if (_waiters.size() == 0)
+ {
+ _logger.error("No Waiters for error saving as last error:" + error.getMessage());
+ _lastException = error;
+ }
+ for (StateWaiter waiter : _waiters)
+ {
+ _logger.error("Notifying Waiters(" + _waiters + ") for error:" + error.getMessage());
+ waiter.error(error);
+ }
}
- public void setProtocolSession(AMQProtocolSession session)
+ /**
+ * This provides a single place that the maximum time for state change to occur can be accessed.
+ * It is currently set via System property amqj.MaximumStateWait
+ *
+ * @return long Milliseconds value for a timeout
+ */
+ public long getWaitTimeout()
{
- _protocolSession = session;
+ return MAXIMUM_STATE_WAIT_TIME;
}
- public MethodRegistry getMethodRegistry()
+ /**
+ * Create and add a new waiter to the notifcation list.
+ *
+ * @param states The waiter will attempt to wait for one of these desired set states to be achived.
+ *
+ * @return the created StateWaiter.
+ */
+ public StateWaiter createWaiter(Set<AMQState> states)
{
- return getProtocolSession().getMethodRegistry();
+ final StateWaiter waiter;
+ synchronized (_stateLock)
+ {
+ waiter = new StateWaiter(this, _currentState, states);
+
+ _waiters.add(waiter);
+ }
+
+ return waiter;
}
- public AMQState attainState(Set<AMQState> stateSet) throws AMQException
+ /**
+ * Remove the waiter from the notification list.
+ *
+ * @param waiter The waiter to remove.
+ */
+ public void removeWaiter(StateWaiter waiter)
{
synchronized (_stateLock)
{
- final long waitUntilTime = System.currentTimeMillis() + MAXIMUM_STATE_WAIT_TIME;
- long waitTime = MAXIMUM_STATE_WAIT_TIME;
-
- while (!stateSet.contains(_currentState) && (waitTime > 0))
- {
- try
- {
- _stateLock.wait(MAXIMUM_STATE_WAIT_TIME);
- }
- catch (InterruptedException e)
- {
- _logger.warn("Thread interrupted");
- }
-
- if (!stateSet.contains(_currentState))
- {
- waitTime = waitUntilTime - System.currentTimeMillis();
- }
- }
-
- if (!stateSet.contains(_currentState))
- {
- _logger.warn("State not achieved within permitted time. Current state " + _currentState
- + ", desired state: " + stateSet);
- throw new AMQException(null, "State not achieved within permitted time. Current state " + _currentState
- + ", desired state: " + stateSet, null);
- }
- return _currentState;
+ _waiters.remove(waiter);
}
+ }
-
+ public Exception getLastException()
+ {
+ return _lastException;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/StateAwareMethodListener.java b/java/client/src/main/java/org/apache/qpid/client/state/StateAwareMethodListener.java
index 8c65f56af3..17d04f4fa3 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/StateAwareMethodListener.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/StateAwareMethodListener.java
@@ -33,6 +33,6 @@ import org.apache.qpid.protocol.AMQMethodEvent;
public interface StateAwareMethodListener<B extends AMQMethodBody>
{
- void methodReceived(AMQStateManager stateManager, B body, int channelId) throws AMQException;
+ void methodReceived(AMQProtocolSession session, B body, int channelId) throws AMQException;
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
index 8b8453a1b0..4695b195d5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java
@@ -20,103 +20,110 @@
*/
package org.apache.qpid.client.state;
+import org.apache.qpid.client.util.BlockingWaiter;
+import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.AMQException;
-
-import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import java.util.Set;
/**
- * Waits for a particular state to be reached.
+ * This is an implementation of the {@link BlockingWaiter} to provide error handing and a waiting mechanism for state
+ * changes.
+ *
+ * On construction the current state and a set of States to await for is provided.
+ *
+ * When await() is called the state at constuction is compared against the awaitStates. If the state at construction is
+ * a desired state then await() returns immediately.
+ *
+ * Otherwise it will block for the set timeout for a desired state to be achieved.
+ *
+ * The state changes are notified via the {@link #process} method.
+ *
+ * Any notified error is handled by the BlockingWaiter and thrown from the {@link #block} method.
+ *
*/
-public class StateWaiter implements StateListener
+public class StateWaiter extends BlockingWaiter<AMQState>
{
private static final Logger _logger = LoggerFactory.getLogger(StateWaiter.class);
- private final AMQState _state;
-
- private volatile boolean _newStateAchieved;
-
- private volatile Throwable _throwable;
-
- private final Object _monitor = new Object();
- private static final long TIME_OUT = 1000 * 60 * 2;
-
- public StateWaiter(AMQState state)
+ Set<AMQState> _awaitStates;
+ private AMQState _startState;
+ private AMQStateManager _stateManager;
+
+ /**
+ *
+ * @param stateManager The StateManager
+ * @param currentState
+ * @param awaitStates
+ */
+ public StateWaiter(AMQStateManager stateManager, AMQState currentState, Set<AMQState> awaitStates)
{
- _state = state;
+ _logger.info("New StateWaiter :" + currentState + ":" + awaitStates);
+ _stateManager = stateManager;
+ _awaitStates = awaitStates;
+ _startState = currentState;
}
- public void waituntilStateHasChanged() throws AMQException
+ /**
+ * When the state is changed this StateWaiter is notified to process the change.
+ *
+ * @param state The new state that has been achieved.
+ * @return
+ */
+ public boolean process(AMQState state)
{
- synchronized (_monitor)
- {
- //
- // The guard is required in case we are woken up by a spurious
- // notify().
- //
- while (!_newStateAchieved && (_throwable == null))
- {
- try
- {
- _logger.debug("State " + _state + " not achieved so waiting...");
- _monitor.wait(TIME_OUT);
- // fixme this won't cause the timeout to exit the loop. need to set _throwable
- }
- catch (InterruptedException e)
- {
- _logger.debug("Interrupted exception caught while waiting: " + e, e);
- }
- }
- }
+ return _awaitStates.contains(state);
+ }
- if (_throwable != null)
- {
- _logger.debug("Throwable reached state waiter: " + _throwable);
- if (_throwable instanceof AMQException)
- {
- throw (AMQException) _throwable;
- }
- else
- {
- throw new AMQException(null, "Error: " + _throwable, _throwable); // FIXME: this will wrap FailoverException in throwable which will prevent it being caught.
- }
- }
+ /**
+ * Await for the requried State to be achieved within the default timeout.
+ * @return The achieved state that was requested.
+ * @throws AMQException The exception that prevented the required state from being achived.
+ */
+ public AMQState await() throws AMQException
+ {
+ return await(_stateManager.getWaitTimeout());
}
- public void stateChanged(AMQState oldState, AMQState newState)
+ /**
+ * Await for the requried State to be achieved.
+ *
+ * <b>It is the responsibility of this class to remove the waiter from the StateManager
+ *
+ * @param timeout The time in milliseconds to wait for any of the states to be achived.
+ * @return The achieved state that was requested.
+ * @throws AMQException The exception that prevented the required state from being achived.
+ */
+ public AMQState await(long timeout) throws AMQException
{
- synchronized (_monitor)
+ try
{
- if (_logger.isDebugEnabled())
+ if (process(_startState))
{
- _logger.debug("stateChanged called changing from :" + oldState + " to :" + newState);
+ return _startState;
}
- if (_state == newState)
+ try
{
- _newStateAchieved = true;
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("New state reached so notifying monitor");
- }
+ return (AMQState) block(timeout);
+ }
+ catch (FailoverException e)
+ {
+ _logger.error("Failover occured whilst waiting for states:" + _awaitStates);
- _monitor.notifyAll();
+ e.printStackTrace();
+ return null;
}
}
- }
-
- public void error(Throwable t)
- {
- synchronized (_monitor)
+ finally
{
- if (_logger.isDebugEnabled())
- {
- _logger.debug("exceptionThrown called");
- }
+ //Prevent any more errors being notified to this waiter.
+ close();
- _throwable = t;
- _monitor.notifyAll();
+ //Remove the waiter from the notifcation list in the statee manager
+ _stateManager.removeWaiter(this);
}
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java b/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java
index 623591e0b6..f0d7feb059 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.client.state.listener;
-import org.apache.qpid.AMQException;
+
import org.apache.qpid.client.protocol.BlockingMethodFrameListener;
import org.apache.qpid.framing.AMQMethodBody;
@@ -34,7 +34,7 @@ public class SpecificMethodFrameListener extends BlockingMethodFrameListener
_expectedClass = expectedClass;
}
- public boolean processMethod(int channelId, AMQMethodBody frame) //throws AMQException
+ public boolean processMethod(int channelId, AMQMethodBody frame)
{
return _expectedClass.isInstance(frame);
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
index a871c754b5..6c12821c74 100644
--- a/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
+++ b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
@@ -40,7 +40,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.net.Socket;
-
/**
* The TransportConnection is a helper class responsible for connecting to an AMQ server. It sets up the underlying
* connector, which currently always uses TCP/IP sockets. It creates the "protocol handler" which deals with MINA
@@ -85,38 +84,18 @@ public class TransportConnection
throw new AMQNoTransportForProtocolException(details, null, null);
}
- /* if (transport == _currentInstance)
- {
- if (transport == VM)
- {
- if (_currentVMPort == details.getPort())
- {
- return _instance;
- }
- }
- else
- {
- return _instance;
- }
- }
-
- _currentInstance = transport;*/
-
- ITransportConnection instance;
switch (transport)
{
case SOCKET:
- instance =
- new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
- {
- public IoConnector newSocketConnector()
- {
- return new ExistingSocketConnector();
- }
- });
- break;
+ return new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
+ {
+ public IoConnector newSocketConnector()
+ {
+ return new ExistingSocketConnector();
+ }
+ });
case TCP:
- instance = new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
+ return new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
{
public IoConnector newSocketConnector()
{
@@ -125,8 +104,8 @@ public class TransportConnection
if (Boolean.getBoolean("qpidnio"))
{
_logger.warn("Using Qpid MultiThreaded NIO - " + (System.getProperties().containsKey("qpidnio")
- ? "Qpid NIO is new default"
- : "Sysproperty 'qpidnio' is set"));
+ ? "Qpid NIO is new default"
+ : "Sysproperty 'qpidnio' is set"));
result = new MultiThreadSocketConnector();
}
else
@@ -141,18 +120,13 @@ public class TransportConnection
return result;
}
});
- break;
case VM:
{
- instance = getVMTransport(details, Boolean.getBoolean("amqj.AutoCreateVMBroker"));
- break;
+ return getVMTransport(details, Boolean.getBoolean("amqj.AutoCreateVMBroker"));
}
default:
- // FIXME: TGM
- throw new AMQNoTransportForProtocolException(details, null, null);
+ throw new AMQNoTransportForProtocolException(details, "Transport not recognised:" + transport, null);
}
-
- return instance;
}
private static int getTransport(String transport)
@@ -180,13 +154,22 @@ public class TransportConnection
{
int port = details.getPort();
- if (!_inVmPipeAddress.containsKey(port))
+ synchronized (_inVmPipeAddress)
{
- if (AutoCreate)
+ if (!_inVmPipeAddress.containsKey(port))
{
if (AutoCreate)
{
- createVMBroker(port);
+ if (AutoCreate)
+ {
+ _logger.warn("Auto Creating InVM Broker on port:" + port);
+ createVMBroker(port);
+ }
+ else
+ {
+ throw new AMQVMBrokerCreationException(null, port, "VM Broker on port " + port
+ + " does not exist. Auto create disabled.", null);
+ }
}
else
{
@@ -194,11 +177,6 @@ public class TransportConnection
+ " does not exist. Auto create disabled.", null);
}
}
- else
- {
- throw new AMQVMBrokerCreationException(null, port, "VM Broker on port " + port
- + " does not exist. Auto create disabled.", null);
- }
}
return new VmPipeTransportConnection(port);
@@ -214,70 +192,73 @@ public class TransportConnection
config.setThreadModel(ReadWriteThreadModel.getInstance());
}
-
- if (!_inVmPipeAddress.containsKey(port))
+ synchronized (_inVmPipeAddress)
{
- _logger.info("Creating InVM Qpid.AMQP listening on port " + port);
- IoHandlerAdapter provider = null;
- try
- {
- VmPipeAddress pipe = new VmPipeAddress(port);
-
- provider = createBrokerInstance(port);
-
- _acceptor.bind(pipe, provider);
- _inVmPipeAddress.put(port, pipe);
- _logger.info("Created InVM Qpid.AMQP listening on port " + port);
- }
- catch (IOException e)
+ if (!_inVmPipeAddress.containsKey(port))
{
- _logger.error("Got IOException.", e);
-
- // Try and unbind provider
+ _logger.info("Creating InVM Qpid.AMQP listening on port " + port);
+ IoHandlerAdapter provider = null;
try
{
VmPipeAddress pipe = new VmPipeAddress(port);
- try
- {
- _acceptor.unbind(pipe);
- }
- catch (Exception ignore)
- {
- // ignore
- }
-
- if (provider == null)
- {
- provider = createBrokerInstance(port);
- }
+ provider = createBrokerInstance(port);
_acceptor.bind(pipe, provider);
+
_inVmPipeAddress.put(port, pipe);
_logger.info("Created InVM Qpid.AMQP listening on port " + port);
}
- catch (IOException justUseFirstException)
+ catch (IOException e)
{
- String because;
- if (e.getCause() == null)
+ _logger.error("Got IOException.", e);
+
+ // Try and unbind provider
+ try
{
- because = e.toString();
+ VmPipeAddress pipe = new VmPipeAddress(port);
+
+ try
+ {
+ _acceptor.unbind(pipe);
+ }
+ catch (Exception ignore)
+ {
+ // ignore
+ }
+
+ if (provider == null)
+ {
+ provider = createBrokerInstance(port);
+ }
+
+ _acceptor.bind(pipe, provider);
+ _inVmPipeAddress.put(port, pipe);
+ _logger.info("Created InVM Qpid.AMQP listening on port " + port);
}
- else
+ catch (IOException justUseFirstException)
{
- because = e.getCause().toString();
- }
+ String because;
+ if (e.getCause() == null)
+ {
+ because = e.toString();
+ }
+ else
+ {
+ because = e.getCause().toString();
+ }
- throw new AMQVMBrokerCreationException(null, port, because + " Stopped binding of InVM Qpid.AMQP", e);
+ throw new AMQVMBrokerCreationException(null, port, because + " Stopped binding of InVM Qpid.AMQP", e);
+ }
}
+
+ }
+ else
+ {
+ _logger.info("InVM Qpid.AMQP on port " + port + " already exits.");
}
}
- else
- {
- _logger.info("InVM Qpid.AMQP on port " + port + " already exits.");
- }
-
}
private static IoHandlerAdapter createBrokerInstance(int port) throws AMQVMBrokerCreationException
@@ -324,7 +305,7 @@ public class TransportConnection
_logger.info("Killing all VM Brokers");
if (_acceptor != null)
{
- _acceptor.unbindAll();
+ _acceptor.unbindAll();
}
synchronized (_inVmPipeAddress)
{
@@ -337,14 +318,17 @@ public class TransportConnection
public static void killVMBroker(int port)
{
- VmPipeAddress pipe = (VmPipeAddress) _inVmPipeAddress.get(port);
- if (pipe != null)
+ synchronized (_inVmPipeAddress)
{
- _logger.info("Killing VM Broker:" + port);
- _inVmPipeAddress.remove(port);
- // This does need to be sychronized as otherwise mina can hang
- // if a new connection is made
- _acceptor.unbind(pipe);
+ VmPipeAddress pipe = (VmPipeAddress) _inVmPipeAddress.get(port);
+ if (pipe != null)
+ {
+ _logger.info("Killing VM Broker:" + port);
+ _inVmPipeAddress.remove(port);
+ // This does need to be sychronized as otherwise mina can hang
+ // if a new connection is made
+ _acceptor.unbind(pipe);
+ }
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java b/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java
new file mode 100644
index 0000000000..67cda957fb
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/util/BlockingWaiter.java
@@ -0,0 +1,348 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQTimeoutException;
+import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQMethodEvent;
+import org.apache.qpid.protocol.AMQMethodListener;
+
+/**
+ * BlockingWaiter is a 'rendezvous' which delegates handling of
+ * incoming Objects to a listener implemented as a sub-class of this and hands off the process or
+ * error to a consumer. The producer of the event does not have to wait for the consumer to take the event, so this
+ * differs from a 'rendezvous' in that sense.
+ *
+ * <p/>BlockingWaiters are used to coordinate when waiting for an an event that expect a response.
+ * They are always used in a 'one-shot' manner, that is, to recieve just one response. Usually the caller has to register
+ * them as method listeners with an event dispatcher and remember to de-register them (in a finally block) once they
+ * have been completed.
+ *
+ * <p/>The {@link #process} must return <tt>true</tt> on any incoming method that it handles. This indicates to
+ * this listeners that the object just processed ends the waiting process.
+ *
+ * <p/>Errors from the producer are rethrown to the consumer.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations </td>
+ * <tr><td> Accept generic objects as events for processing via {@link #process}. <td>
+ * <tr><td> Delegate handling and undserstanding of the object to a concrete implementation. <td>
+ * <tr><td> Block until {@link #process} determines that waiting is no longer required <td>
+ * <tr><td> Propagate the most recent exception to the consumer.<td>
+ * </table>
+ *
+ * @todo Interuption is caught but not handled. This could be allowed to fall through. This might actually be usefull
+ * for fail-over where a thread is blocking when failure happens, it could be interrupted to abandon or retry
+ * when this happens. At the very least, restore the interrupted status flag.
+ * @todo If the retrotranslator can handle it, could use a SynchronousQueue to implement this rendezvous. Need to
+ * check that SynchronousQueue has a non-blocking put method available.
+ */
+public abstract class BlockingWaiter<T>
+{
+ /** This flag is used to indicate that the blocked for method has been received. */
+ private volatile boolean _ready = false;
+
+ /** This flag is used to indicate that the received error has been processed. */
+ private volatile boolean _errorAck = false;
+
+ /** Used to protect the shared event and ready flag between the producer and consumer. */
+ private final ReentrantLock _lock = new ReentrantLock();
+
+ /** Used to signal that a method has been received */
+ private final Condition _receivedCondition = _lock.newCondition();
+
+ /** Used to signal that a error has been processed */
+ private final Condition _errorConditionAck = _lock.newCondition();
+
+ /** Used to hold the most recent exception that is passed to the {@link #error(Exception)} method. */
+ private volatile Exception _error;
+
+ /** Holds the incomming Object. */
+ protected Object _doneObject = null;
+ private AtomicBoolean _waiting = new AtomicBoolean(false);
+ private boolean _closed = false;
+
+ /**
+ * Delegates processing of the incomming object to the handler.
+ *
+ * @param object The object to process.
+ *
+ * @return <tt>true</tt> if the waiting is complete, <tt>false</tt> if waiting should continue.
+ */
+ public abstract boolean process(T object);
+
+ /**
+ * An Object has been received and should be processed to see if our wait condition has been reached.
+ *
+ * @param object The object received.
+ *
+ * @return <tt>true</tt> if the waiting is complete, <tt>false</tt> if waiting should continue.
+ */
+ public boolean received(T object)
+ {
+
+ boolean ready = process(object);
+
+ if (ready)
+ {
+ // we only update the flag from inside the synchronized block
+ // so that the blockForFrame method cannot "miss" an update - it
+ // will only ever read the flag from within the synchronized block
+ _lock.lock();
+ try
+ {
+ _doneObject = object;
+ _ready = ready;
+ _receivedCondition.signal();
+ }
+ finally
+ {
+ _lock.unlock();
+ }
+ }
+
+ return ready;
+ }
+
+ /**
+ * Blocks until an object is received that is handled by process, or the specified timeout
+ * has passed.
+ *
+ * Once closed any attempt to wait will throw an exception.
+ *
+ * @param timeout The timeout in milliseconds.
+ *
+ * @return The object that resolved the blocking.
+ *
+ * @throws AMQException
+ * @throws FailoverException
+ */
+ public Object block(long timeout) throws AMQException, FailoverException
+ {
+ long nanoTimeout = TimeUnit.MILLISECONDS.toNanos(timeout);
+
+ _lock.lock();
+
+ try
+ {
+ if (_closed)
+ {
+ throw throwClosedException();
+ }
+
+ if (_error == null)
+ {
+ _waiting.set(true);
+
+ while (!_ready)
+ {
+ try
+ {
+ if (timeout == -1)
+ {
+ _receivedCondition.await();
+ }
+ else
+ {
+ nanoTimeout = _receivedCondition.awaitNanos(nanoTimeout);
+
+ if (nanoTimeout <= 0 && !_ready && _error == null)
+ {
+ _error = new AMQTimeoutException("Server did not respond in a timely fashion", null);
+ _ready = true;
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println(e.getMessage());
+ // IGNORE -- //fixme this isn't ideal as being interrupted isn't equivellant to sucess
+ // if (!_ready && timeout != -1)
+ // {
+ // _error = new AMQException("Server did not respond timely");
+ // _ready = true;
+ // }
+ }
+ }
+ }
+
+ if (_error != null)
+ {
+ if (_error instanceof AMQException)
+ {
+ throw (AMQException) _error;
+ }
+ else if (_error instanceof FailoverException)
+ {
+ // This should ensure that FailoverException is not wrapped and can be caught.
+ throw (FailoverException) _error; // needed to expose FailoverException.
+ }
+ else
+ {
+ throw new AMQException("Woken up due to " + _error.getClass(), _error);
+ }
+ }
+
+ }
+ finally
+ {
+ _waiting.set(false);
+
+ //Release Error handling thread
+ if (_error != null)
+ {
+ _errorAck = true;
+ _errorConditionAck.signal();
+
+ _error = null;
+ }
+ _lock.unlock();
+ }
+
+ return _doneObject;
+ }
+
+ /**
+ * This is a callback, called when an error has occured that should interupt any waiter.
+ * It is also called from within this class to avoid code repetition but it should only be called by the MINA threads.
+ *
+ * Once closed any notification of an exception will be ignored.
+ *
+ * @param e The exception being propogated.
+ */
+ public void error(Exception e)
+ {
+ // set the error so that the thread that is blocking (against blockForFrame())
+ // can pick up the exception and rethrow to the caller
+
+ _lock.lock();
+
+ if (_closed)
+ {
+ return;
+ }
+
+ if (_error == null)
+ {
+ _error = e;
+ }
+ else
+ {
+ System.err.println("WARNING: new error arrived while old one not yet processed");
+ }
+
+ try
+ {
+ if (_waiting.get())
+ {
+
+ _ready = true;
+ _receivedCondition.signal();
+
+ while (!_errorAck)
+ {
+ try
+ {
+ _errorConditionAck.await();
+ }
+ catch (InterruptedException e1)
+ {
+ System.err.println(e.getMessage());
+ }
+ }
+ _errorAck = false;
+ }
+ }
+ finally
+ {
+ _lock.unlock();
+ }
+ }
+
+ /**
+ * Close this Waiter so that no more errors are processed.
+ * This is a preventative method to ensure that a second error thread does not get stuck in the error method after
+ * the await has returned. This has not happend but in practise but if two errors occur on the Connection at
+ * the same time then it is conceiveably possible for the second to get stuck if the first one is processed by a
+ * waiter.
+ *
+ * Once closed any attempt to wait will throw an exception.
+ * Any notification of an exception will be ignored.
+ */
+ public void close()
+ {
+ _lock.lock();
+ try
+ {
+ //if we have already closed then our job is done.
+ if (_closed)
+ {
+ return;
+ }
+
+ //Close Waiter so no more exceptions are processed
+ _closed = true;
+
+ //Wake up any await() threads
+
+ //If we are waiting then use the error() to wake them up.
+ if (_waiting.get())
+ {
+ error(throwClosedException());
+ }
+ //If they are not waiting then there is nothing to do.
+
+ // Wake up any error handling threads
+
+ if (!_errorAck)
+ {
+ _errorAck = true;
+ _errorConditionAck.signal();
+
+ _error = null;
+ }
+ }
+ finally
+ {
+ _lock.unlock();
+ }
+ }
+
+ /**
+ * Helper method to generate the a closed Exception.
+ *
+ * todo: This should be converted to something more friendly.
+ *
+ * @return AMQException to throw to waiters when the Waiter is closed.
+ */
+ private AMQException throwClosedException()
+ {
+ return new AMQException(null, "Waiter was closed.", null);
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java b/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java
index 0fc39a9318..bddbc329ab 100644
--- a/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java
+++ b/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java
@@ -21,8 +21,10 @@
package org.apache.qpid.client.util;
import java.util.Iterator;
+import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ConcurrentLinkedQueue;
/**
* A blocking queue that emits events above a user specified threshold allowing the caller to take action (e.g. flow
@@ -35,7 +37,7 @@ import java.util.concurrent.LinkedBlockingQueue;
public class FlowControllingBlockingQueue
{
/** This queue is bounded and is used to store messages before being dispatched to the consumer */
- private final BlockingQueue _queue = new LinkedBlockingQueue();
+ private final Queue _queue = new ConcurrentLinkedQueue();
private final int _flowControlHighThreshold;
private final int _flowControlLowThreshold;
@@ -71,7 +73,17 @@ public class FlowControllingBlockingQueue
public Object take() throws InterruptedException
{
- Object o = _queue.take();
+ Object o = _queue.poll();
+ if(o == null)
+ {
+ synchronized(this)
+ {
+ while((o = _queue.poll())==null)
+ {
+ wait();
+ }
+ }
+ }
if (_listener != null)
{
synchronized (_listener)
@@ -88,7 +100,12 @@ public class FlowControllingBlockingQueue
public void add(Object o)
{
- _queue.add(o);
+ synchronized(this)
+ {
+ _queue.add(o);
+
+ notifyAll();
+ }
if (_listener != null)
{
synchronized (_listener)
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java b/java/client/src/main/java/org/apache/qpid/filter/ArithmeticExpression.java
index 279716598d..56d1bdcdc5 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/ArithmeticExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/BinaryExpression.java b/java/client/src/main/java/org/apache/qpid/filter/BinaryExpression.java
index 465b504ae3..f97f858fad 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/BinaryExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/BinaryExpression.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
/**
* An expression which performs an operation on two expression values.
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/BooleanExpression.java b/java/client/src/main/java/org/apache/qpid/filter/BooleanExpression.java
index 9a3b1c3106..cc24c81729 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/BooleanExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/BooleanExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java b/java/client/src/main/java/org/apache/qpid/filter/ComparisonExpression.java
index 46f387b293..adf360698b 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/ComparisonExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
import java.util.HashSet;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/ConstantExpression.java b/java/client/src/main/java/org/apache/qpid/filter/ConstantExpression.java
index 26aeec2de8..447de914a4 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/ConstantExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/ConstantExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
import java.math.BigDecimal;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/Expression.java b/java/client/src/main/java/org/apache/qpid/filter/Expression.java
index bdc3c9cccc..e578775a77 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/Expression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/Expression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java b/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java
index c73da1682a..dcfb9a9940 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/JMSSelectorFilter.java
@@ -15,12 +15,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.filter.selector.SelectorParser;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.filter.selector.SelectorParser;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/LogicExpression.java b/java/client/src/main/java/org/apache/qpid/filter/LogicExpression.java
index 7f5909df43..d7aabd5a46 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/LogicExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/LogicExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/MessageFilter.java b/java/client/src/main/java/org/apache/qpid/filter/MessageFilter.java
index aa1303a373..a775080d81 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/MessageFilter.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/MessageFilter.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/PropertyExpression.java b/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java
index 5ea2004d75..2c05f5ce0f 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/PropertyExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/PropertyExpression.java
@@ -15,12 +15,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpid.framing.CommonContentHeaderProperties;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.ErrorCode;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -54,20 +53,7 @@ public class PropertyExpression implements Expression
{
public Object evaluate(AbstractJMSMessage message)
{
- try
- {
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- AMQShortString replyTo = _properties.getReplyTo();
-
- return (replyTo == null) ? null : replyTo.toString();
- }
- catch (Exception e)
- {
- _logger.warn("Error evaluating property", e);
-
- return null;
- }
+ return message.getReplyToString();
}
});
@@ -77,13 +63,9 @@ public class PropertyExpression implements Expression
{
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- AMQShortString type = _properties.getType();
-
- return (type == null) ? null : type.toString();
+ return message.getJMSType();
}
- catch (Exception e)
+ catch (JMSException e)
{
_logger.warn("Error evaluating property", e);
@@ -107,7 +89,7 @@ public class PropertyExpression implements Expression
return mode;
}
- catch (Exception e)
+ catch (JMSException e)
{
_logger.warn("Error evaluating property",e);
}
@@ -122,9 +104,7 @@ public class PropertyExpression implements Expression
{
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- return (int) _properties.getPriority();
+ return message.getJMSPriority();
}
catch (Exception e)
{
@@ -142,13 +122,9 @@ public class PropertyExpression implements Expression
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- AMQShortString messageId = _properties.getMessageId();
-
- return (messageId == null) ? null : messageId;
+ return message.getJMSMessageID();
}
- catch (Exception e)
+ catch (JMSException e)
{
_logger.warn("Error evaluating property",e);
@@ -164,9 +140,7 @@ public class PropertyExpression implements Expression
{
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- return _properties.getTimestamp();
+ return message.getJMSTimestamp();
}
catch (Exception e)
{
@@ -185,12 +159,9 @@ public class PropertyExpression implements Expression
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- AMQShortString correlationId = _properties.getCorrelationId();
- return (correlationId == null) ? null : correlationId.toString();
+ return message.getJMSCorrelationID();
}
- catch (Exception e)
+ catch (JMSException e)
{
_logger.warn("Error evaluating property",e);
@@ -207,11 +178,9 @@ public class PropertyExpression implements Expression
try
{
- CommonContentHeaderProperties _properties =
- message.getContentHeaderProperties();
- return _properties.getExpiration();
+ return message.getJMSExpiration();
}
- catch (Exception e)
+ catch (JMSException e)
{
_logger.warn("Error evaluating property",e);
return null;
@@ -257,13 +226,20 @@ public class PropertyExpression implements Expression
else
{
- CommonContentHeaderProperties _properties = message.getContentHeaderProperties();
- if (_logger.isDebugEnabled())
+ try
+ {
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Looking up property:" + name);
+ _logger.debug("Properties are:" + message.getPropertyNames());
+ }
+ return message.getObjectProperty(name);
+ }
+ catch(JMSException e)
{
- _logger.debug("Looking up property:" + name);
- _logger.debug("Properties are:" + _properties.getHeaders().keySet());
+ throw new QpidException("Exception evaluating properties for filter", ErrorCode.INTERNAL_ERROR, e);
}
- return _properties.getHeaders().getObject(name);
}
}
diff --git a/java/client/src/main/java/org/apache/qpidity/filter/UnaryExpression.java b/java/client/src/main/java/org/apache/qpid/filter/UnaryExpression.java
index f73449679c..b620b107c4 100644
--- a/java/client/src/main/java/org/apache/qpidity/filter/UnaryExpression.java
+++ b/java/client/src/main/java/org/apache/qpid/filter/UnaryExpression.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.filter;
+package org.apache.qpid.filter;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import org.apache.qpid.client.message.AbstractJMSMessage;
import java.math.BigDecimal;
diff --git a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
index 72ba16086d..0316255b2c 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java
@@ -48,7 +48,7 @@ public interface BrokerDetails
public static final long DEFAULT_CONNECT_TIMEOUT = 30000L;
public static final boolean USE_SSL_DEFAULT = false;
- // pulled these properties from the new BrokerDetails class in the qpidity package
+ // pulled these properties from the new BrokerDetails class in the qpid package
public static final String PROTOCOL_TCP = "tcp";
public static final String PROTOCOL_TLS = "tls";
diff --git a/java/client/src/main/java/org/apache/qpid/jms/Message.java b/java/client/src/main/java/org/apache/qpid/jms/Message.java
index e65f9ad2f4..53c615a1fd 100644
--- a/java/client/src/main/java/org/apache/qpid/jms/Message.java
+++ b/java/client/src/main/java/org/apache/qpid/jms/Message.java
@@ -24,5 +24,7 @@ import javax.jms.JMSException;
public interface Message extends javax.jms.Message
{
+ public static final String JMS_TYPE = "x-jms-type";
+
public void acknowledgeThis() throws JMSException;
}
diff --git a/java/client/src/main/java/org/apache/qpidity/naming/ReadOnlyContext.java b/java/client/src/main/java/org/apache/qpid/naming/ReadOnlyContext.java
index c73d6e4b35..59ec4cfba7 100644
--- a/java/client/src/main/java/org/apache/qpidity/naming/ReadOnlyContext.java
+++ b/java/client/src/main/java/org/apache/qpid/naming/ReadOnlyContext.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.naming;
+package org.apache.qpid.naming;
import org.apache.qpid.jndi.NameParserImpl;
diff --git a/java/client/src/main/java/org/apache/qpidity/naming/jndi.properties b/java/client/src/main/java/org/apache/qpid/naming/jndi.properties
index e451cf53fa..830de5f619 100644
--- a/java/client/src/main/java/org/apache/qpidity/naming/jndi.properties
+++ b/java/client/src/main/java/org/apache/qpid/naming/jndi.properties
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-java.naming.factory.initial = org.apache.qpidity.naming.PropertiesFileInitialConextFactory
+java.naming.factory.initial = org.apache.qpid.naming.PropertiesFileInitialConextFactory
# use the following property to configure the default connector
#java.naming.provider.url - ignored.
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/Client.java b/java/client/src/main/java/org/apache/qpid/nclient/Client.java
index bc88160137..af0e724e42 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/Client.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/Client.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
import java.util.List;
import java.util.UUID;
@@ -25,34 +25,31 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.TimeUnit;
import org.apache.qpid.client.url.URLParser_0_10;
import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.url.QpidURL;
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.ProtocolException;
-import org.apache.qpidity.nclient.impl.ClientSession;
-import org.apache.qpidity.nclient.impl.ClientSessionDelegate;
-import org.apache.qpidity.transport.Channel;
-import org.apache.qpidity.transport.ClientDelegate;
-import org.apache.qpidity.transport.Connection;
-import org.apache.qpidity.transport.ConnectionClose;
-import org.apache.qpidity.transport.ConnectionCloseCode;
-import org.apache.qpidity.transport.ConnectionCloseOk;
-import org.apache.qpidity.transport.ConnectionEvent;
-import org.apache.qpidity.transport.TransportConstants;
-import org.apache.qpidity.transport.ProtocolHeader;
-import org.apache.qpidity.transport.SessionDelegate;
-import org.apache.qpidity.transport.network.io.IoHandler;
-import org.apache.qpidity.transport.network.mina.MinaHandler;
-import org.apache.qpidity.transport.network.nio.NioHandler;
+import org.apache.qpid.ErrorCode;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.nclient.impl.ClientSession;
+import org.apache.qpid.nclient.impl.ClientSessionDelegate;
+import org.apache.qpid.transport.Channel;
+import org.apache.qpid.transport.ClientDelegate;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionClose;
+import org.apache.qpid.transport.ConnectionCloseCode;
+import org.apache.qpid.transport.ConnectionCloseOk;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.ProtocolVersionException;
+import org.apache.qpid.transport.SessionDelegate;
+import org.apache.qpid.transport.network.io.IoTransport;
+import org.apache.qpid.transport.network.mina.MinaHandler;
+import org.apache.qpid.transport.network.nio.NioHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class Client implements org.apache.qpidity.nclient.Connection
+public class Client implements org.apache.qpid.nclient.Connection
{
private Connection _conn;
private ClosedListener _closedListner;
@@ -60,12 +57,15 @@ public class Client implements org.apache.qpidity.nclient.Connection
private static Logger _logger = LoggerFactory.getLogger(Client.class);
private Condition closeOk;
private boolean closed = false;
+ private long timeout = 60000;
+
+ private ProtocolHeader header = null;
/**
*
* @return returns a new connection to the broker.
*/
- public static org.apache.qpidity.nclient.Connection createConnection()
+ public static org.apache.qpid.nclient.Connection createConnection()
{
return new Client();
}
@@ -80,7 +80,6 @@ public class Client implements org.apache.qpidity.nclient.Connection
ClientDelegate connectionDelegate = new ClientDelegate()
{
private boolean receivedClose = false;
- private String _unsupportedProtocol;
public SessionDelegate getSessionDelegate()
{
return new ClientSessionDelegate();
@@ -123,6 +122,7 @@ public class Client implements org.apache.qpidity.nclient.Connection
@Override public void connectionClose(Channel context, ConnectionClose connectionClose)
{
+ super.connectionClose(context, connectionClose);
ErrorCode errorCode = ErrorCode.get(connectionClose.getReplyCode().getValue());
if (_closedListner == null && errorCode != ErrorCode.NO_ERROR)
{
@@ -139,28 +139,18 @@ public class Client implements org.apache.qpidity.nclient.Connection
this.receivedClose = true;
}
-
@Override public void init(Channel ch, ProtocolHeader hdr)
{
// TODO: once the merge is done we'll need to update this code
- // for handling 0.8 protocol version type i.e. major=8 and minor=0 :(
- if (hdr.getMajor() != TransportConstants.getVersionMajor()
- || hdr.getMinor() != TransportConstants.getVersionMinor())
+ // for handling 0.8 protocol version type i.e. major=8 and mino
+ if (hdr.getMajor() != 0 || hdr.getMinor() != 10)
{
- _unsupportedProtocol = TransportConstants.getVersionMajor() + "." +
- TransportConstants.getVersionMinor();
- TransportConstants.setVersionMajor( hdr.getMajor() );
- TransportConstants.setVersionMinor( hdr.getMinor() );
+ Client.this.header = hdr;
_lock.lock();
negotiationComplete.signalAll();
_lock.unlock();
}
}
-
- @Override public String getUnsupportedProtocol()
- {
- return _unsupportedProtocol;
- }
};
connectionDelegate.setCondition(_lock,negotiationComplete);
@@ -168,15 +158,16 @@ public class Client implements org.apache.qpidity.nclient.Connection
connectionDelegate.setPassword(password);
connectionDelegate.setVirtualHost(virtualHost);
- if (System.getProperty("transport","mina").equalsIgnoreCase("nio"))
+ String transport = System.getProperty("transport","io");
+ if (transport.equalsIgnoreCase("nio"))
{
_logger.info("using NIO Transport");
_conn = NioHandler.connect(host, port,connectionDelegate);
}
- else if (System.getProperty("transport","mina").equalsIgnoreCase("io"))
+ else if (transport.equalsIgnoreCase("io"))
{
_logger.info("using Plain IO Transport");
- _conn = IoHandler.connect(host, port,connectionDelegate);
+ _conn = IoTransport.connect(host, port,connectionDelegate);
}
else
{
@@ -186,23 +177,20 @@ public class Client implements org.apache.qpidity.nclient.Connection
}
// XXX: hardcoded version numbers
- _conn.send(new ConnectionEvent(0, new ProtocolHeader(1, TransportConstants.getVersionMajor(),
- TransportConstants.getVersionMinor())));
+ _conn.send(new ProtocolHeader(1, 0, 10));
try
{
- negotiationComplete.await();
- if( connectionDelegate.getUnsupportedProtocol() != null )
+ negotiationComplete.await(timeout, TimeUnit.MILLISECONDS);
+ if (header != null)
{
_conn.close();
- throw new ProtocolException("Unsupported protocol version: " + connectionDelegate.getUnsupportedProtocol()
- , ErrorCode.UNSUPPORTED_PROTOCOL, null);
-
+ throw new ProtocolVersionException(header.getMajor(), header.getMinor());
}
}
catch (InterruptedException e)
{
- //
+ throw new RuntimeException(e);
}
finally
{
@@ -257,7 +245,6 @@ public class Client implements org.apache.qpidity.nclient.Connection
{
try
{
- long timeout = 60000;
long start = System.currentTimeMillis();
long elapsed = 0;
while (!closed && elapsed < timeout)
@@ -289,20 +276,6 @@ public class Client implements org.apache.qpidity.nclient.Connection
ssn.attach(ch);
ssn.sessionAttach(ssn.getName());
ssn.sessionRequestTimeout(expiryInSeconds);
- String transport = System.getProperty("transport","mina");
-
- try
- {
- if (Boolean.getBoolean("batch") && ("io".equalsIgnoreCase(transport) || "nio".equalsIgnoreCase(transport)))
- {
- _logger.debug("using batch mode in transport " + transport);
- IoHandler.startBatchingFrames(_conn.getConnectionId());
- }
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
return ssn;
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/ClosedListener.java b/java/client/src/main/java/org/apache/qpid/nclient/ClosedListener.java
index c0c6978a14..4cf0cab1ec 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/ClosedListener.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/ClosedListener.java
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
-import org.apache.qpidity.ErrorCode;
+import org.apache.qpid.ErrorCode;
/**
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/Connection.java b/java/client/src/main/java/org/apache/qpid/nclient/Connection.java
index 49167750d1..2d5b50b33a 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/Connection.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/Connection.java
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
/**
* This represents a physical connection to a broker.
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java b/java/client/src/main/java/org/apache/qpid/nclient/DtxSession.java
index 6f15f16470..8a859f2d84 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/DtxSession.java
@@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
-import org.apache.qpidity.transport.Future;
-import org.apache.qpidity.transport.GetTimeoutResult;
-import org.apache.qpidity.transport.Option;
-import org.apache.qpidity.transport.RecoverResult;
-import org.apache.qpidity.transport.XaResult;
-import org.apache.qpidity.transport.Xid;
+import org.apache.qpid.transport.Future;
+import org.apache.qpid.transport.GetTimeoutResult;
+import org.apache.qpid.transport.Option;
+import org.apache.qpid.transport.RecoverResult;
+import org.apache.qpid.transport.XaResult;
+import org.apache.qpid.transport.Xid;
/**
* The resources for this session are controlled under the scope of a distributed transaction.
@@ -83,7 +83,7 @@ public interface DtxSession extends Session
*
* @param xid Specifies the xid of the transaction branch to be forgotten.
*/
- public void dtxForget(Xid xid);
+ public void dtxForget(Xid xid, Option ... options);
/**
* This method obtains the current transaction timeout value in seconds. If set-timeout was not
@@ -93,7 +93,7 @@ public interface DtxSession extends Session
* @param xid Specifies the xid of the transaction branch used for getting the timeout.
* @return The current transaction timeout value in seconds.
*/
- public Future<GetTimeoutResult> dtxGetTimeout(Xid xid);
+ public Future<GetTimeoutResult> dtxGetTimeout(Xid xid, Option ... options);
/**
* This method prepares any message produced or consumed on behalf of xid, ready for commitment.
@@ -109,14 +109,14 @@ public interface DtxSession extends Session
* <p/>
* xa-rbtimeout: The work represented by this transaction branch took too long.
*/
- public Future<XaResult> dtxPrepare(Xid xid);
+ public Future<XaResult> dtxPrepare(Xid xid, Option ... options);
/**
* This method is called to obtain a list of transaction branches that are in a prepared or
* heuristically completed state.
* @return a array of xids to be recovered.
*/
- public Future<RecoverResult> dtxRecover();
+ public Future<RecoverResult> dtxRecover(Option ... options);
/**
* This method rolls back the work associated with xid. Any produced messages are discarded and
@@ -125,7 +125,7 @@ public interface DtxSession extends Session
* @param xid Specifies the xid of the transaction branch to be rolled back.
* @return Confirms to the client that the transaction branch is rolled back or specifies the error condition.
*/
- public Future<XaResult> dtxRollback(Xid xid);
+ public Future<XaResult> dtxRollback(Xid xid, Option ... options);
/**
* Sets the specified transaction branch timeout value in seconds.
@@ -133,5 +133,5 @@ public interface DtxSession extends Session
* @param xid Specifies the xid of the transaction branch for setting the timeout.
* @param timeout The transaction timeout value in seconds.
*/
- public void dtxSetTimeout(Xid xid, long timeout);
+ public void dtxSetTimeout(Xid xid, long timeout, Option ... options);
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/JMSTestCase.java b/java/client/src/main/java/org/apache/qpid/nclient/JMSTestCase.java
index feb4c1c94d..4e1b9058e6 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/JMSTestCase.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/JMSTestCase.java
@@ -1,4 +1,4 @@
- package org.apache.qpidity.nclient;
+ package org.apache.qpid.nclient;
import java.util.Enumeration;
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/MessagePartListener.java b/java/client/src/main/java/org/apache/qpid/nclient/MessagePartListener.java
index 7c7881502a..6f07dcb469 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/MessagePartListener.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/MessagePartListener.java
@@ -15,11 +15,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.Header;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageTransfer;
/**
* Assembles message parts.
@@ -33,31 +34,13 @@ import org.apache.qpidity.transport.Header;
* are transferred.
*/
public interface MessagePartListener
-{
- /**
- * Indicates the Message transfer has started.
- *
- * @param transferId The message transfer ID.
- */
- public void messageTransfer(int transferId);
-
- /**
- * Add the following a header to the message being received.
- *
- * @param header Either <code>DeliveryProperties</code> or <code>ApplicationProperties</code>
- */
- public void messageHeader(Header header);
+{
/**
- * Add the following byte array to the content of the message being received
+ * Inform the listener of the message transfer
*
- * @param src Data to be added or streamed.
- */
- public void data(ByteBuffer src);
-
- /**
- * Indicates that the message has been fully received.
+ * @param xfr the message transfer object
*/
- public void messageReceived();
+ public void messageTransfer(MessageTransfer xfr);
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/Session.java b/java/client/src/main/java/org/apache/qpid/nclient/Session.java
index 717ea43654..0d84394c7c 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/Session.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/Session.java
@@ -16,14 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient;
+package org.apache.qpid.nclient;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
-import org.apache.qpidity.transport.*;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.transport.*;
+import org.apache.qpid.api.Message;
/**
* <p>A session is associated with a connection.
@@ -65,9 +65,9 @@ public interface Session
public void close();
- public void sessionDetach(byte[] name);
+ public void sessionDetach(byte[] name, Option ... options);
- public void sessionRequestTimeout(long expiry);
+ public void sessionRequestTimeout(long expiry, Option ... options);
public byte[] getName();
@@ -109,42 +109,6 @@ public interface Session
/**
- * <p>This transfer streams a complete message using a single method.
- * It uses pull-semantics instead of doing a push.</p>
- * <p>Data is pulled from a Message object using read()
- * and pushed using messageTransfer() and headers() followed by data() and endData().
- * <br><b><i>This method should only be used by large messages</b></i><br>
- * There are two convenience Message classes to do this.
- * <ul>
- * <li> <code>{@link org.apache.qpidity.nclient.util.FileMessage}</code>
- * <li> <code>{@link org.apache.qpidity.nclient.util.StreamingMessage}</code>
- * </ul>
- * You can also implement a <code>Message</code> interface to wrap any
- * data stream.
- * </p>
- *
- * @param destination The exchange the message is being sent to.
- * @param msg The Message to be sent.
- * @param confirmMode <ul> </li>off ({@link Session#TRANSFER_CONFIRM_MODE_NOT_REQUIRED}): confirmation
- * is not required. Once a message has been transferred in pre-acquire
- * mode (or once acquire has been sent in no-acquire mode) the message is considered
- * transferred.
- * <p/>
- * <li> on ({@link Session#TRANSFER_CONFIRM_MODE_REQUIRED}): an acquired message
- * is not considered transferred until the original
- * transfer is complete. A complete transfer is signaled by execution.complete.
- * </ul>
- * @param acquireMode <ul>
- * <li> no-acquire ({@link Session#TRANSFER_ACQUIRE_MODE_NO_ACQUIRE}): the message
- * must be explicitly acquired.
- * <li> pre-acquire ({@link Session#TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE}): the message
- * is acquired when the transfer starts.
- * </ul>
- * @throws java.io.IOException If transferring a message fails due to some internal communication error, an exception is thrown.
- */
- public void messageStream(String destination, Message msg, short confirmMode, short acquireMode) throws IOException;
-
- /**
* This command transfers a message between two peers.
*
* @param destination Specifies the destination to which the message is to be transferred.
@@ -153,46 +117,32 @@ public interface Session
*
* @param acquireMode Indicates whether or not the transferred message has been acquired.
*/
- public void messageTransfer(String destination, MessageAcceptMode acceptMode, MessageAcquireMode acquireMode);
+ public void messageTransfer(String destination, MessageAcceptMode acceptMode, MessageAcquireMode acquireMode,
+ Header header, ByteBuffer body, Option ... options);
/**
- * Make a set of headers to be sent together with a message
- *
- * @param headers headers to be added
- * @see org.apache.qpidity.transport.DeliveryProperties
- * @see org.apache.qpidity.transport.MessageProperties
- * @return The added headers.
- */
- public Header header(Struct... headers);
-
- /**
- * Add a byte array to the content of the message being sent.
- *
- * @param data Data to be added.
- */
- public void data(byte[] data);
-
- /**
- * A Add a ByteBuffer to the content of the message being sent.
- * <p> Note that only the data between the buffer's current position and the
- * buffer limit is added.
- * It is therefore recommended to flip the buffer before adding it to the message,
+ * This command transfers a message between two peers.
*
- * @param buf Data to be added.
+ * @param destination Specifies the destination to which the message is to be transferred.
+ * @param acceptMode Indicates whether message.accept, session.complete,
+ * or nothing at all is required to indicate successful transfer of the message.
+ *
+ * @param acquireMode Indicates whether or not the transferred message has been acquired.
*/
- public void data(ByteBuffer buf);
+ public void messageTransfer(String destination, MessageAcceptMode acceptMode, MessageAcquireMode acquireMode,
+ Header header, byte[] body, Option ... options);
/**
- * Add a string to the content of the message being sent.
+ * This command transfers a message between two peers.
*
- * @param str String to be added.
- */
- public void data(String str);
-
- /**
- * Signals the end of data for the message.
+ * @param destination Specifies the destination to which the message is to be transferred.
+ * @param acceptMode Indicates whether message.accept, session.complete,
+ * or nothing at all is required to indicate successful transfer of the message.
+ *
+ * @param acquireMode Indicates whether or not the transferred message has been acquired.
*/
- public void endData();
+ public void messageTransfer(String destination, MessageAcceptMode acceptMode, MessageAcquireMode acquireMode,
+ Header header, String body, Option ... options);
//------------------------------------------------------
// Messaging methods
@@ -207,7 +157,7 @@ public interface Session
* <ul>
* <li>{@link Option#EXCLUSIVE}: <p> Requests exclusive subscription access, so that only this
* subscription can access the queue.
- * <li>{@link Option#NO_OPTION}: <p> This is an empty option, and has no effect.
+ * <li>{@link Option#NONE}: <p> This is an empty option, and has no effect.
* </ul>
*
* @param queue The queue that the receiver is receiving messages from.
@@ -228,9 +178,9 @@ public interface Session
* acquired when the transfer starts.
* </ul>
* @param listener The listener for this destination. To transfer large messages
- * use a {@link org.apache.qpidity.nclient.MessagePartListener}.
+ * use a {@link org.apache.qpid.nclient.MessagePartListener}.
* @param options Set of options. Valid options are {{@link Option#EXCLUSIVE}
- * and {@link Option#NO_OPTION}.
+ * and {@link Option#NONE}.
* @param filter A set of filters for the subscription. The syntax and semantics of these filters varies
* according to the provider's implementation.
*/
@@ -246,7 +196,7 @@ public interface Session
*
* @param destination The destination to be cancelled.
*/
- public void messageCancel(String destination);
+ public void messageCancel(String destination, Option ... options);
/**
* Associate a message listener with a destination.
@@ -274,7 +224,7 @@ public interface Session
* @param mode <ul> <li>credit ({@link Session#MESSAGE_FLOW_MODE_CREDIT}): choose credit based flow control
* <li> window ({@link Session#MESSAGE_FLOW_MODE_WINDOW}): choose window based flow control</ul>
*/
- public void messageSetFlowMode(String destination, MessageFlowMode mode);
+ public void messageSetFlowMode(String destination, MessageFlowMode mode, Option ... options);
/**
@@ -295,7 +245,7 @@ public interface Session
* </ul>
* @param value Number of credits, a value of 0 indicates an infinite amount of credit.
*/
- public void messageFlow(String destination, MessageCreditUnit unit, long value);
+ public void messageFlow(String destination, MessageCreditUnit unit, long value, Option ... options);
/**
* Forces the broker to exhaust its credit supply.
@@ -304,7 +254,7 @@ public interface Session
*
* @param destination The destination on which the credit supply is to be exhausted.
*/
- public void messageFlush(String destination);
+ public void messageFlush(String destination, Option ... options);
/**
* On receipt of this method, the brokers set credit to zero for a given
@@ -314,7 +264,7 @@ public interface Session
*
* @param destination The destination on which to reset credit.
*/
- public void messageStop(String destination);
+ public void messageStop(String destination, Option ... options);
/**
* Acknowledge the receipt of a range of messages.
@@ -338,7 +288,7 @@ public interface Session
* failed).
* @param text String describing the reason for a message transfer rejection.
*/
- public void messageReject(RangeSet ranges, MessageRejectCode code, String text);
+ public void messageReject(RangeSet ranges, MessageRejectCode code, String text, Option ... options);
/**
* As it is possible that the broker does not manage to reject some messages, after completion of
@@ -367,7 +317,7 @@ public interface Session
* @param ranges Ranges of messages to be acquired.
* @return Indicates the acquired messages
*/
- public Future<Acquired> messageAcquire(RangeSet ranges);
+ public Future<Acquired> messageAcquire(RangeSet ranges, Option ... options);
/**
* Give up responsibility for processing ranges of messages.
@@ -384,21 +334,21 @@ public interface Session
/**
* Selects the session for local transaction support.
*/
- public void txSelect();
+ public void txSelect(Option ... options);
/**
* Commit the receipt and delivery of all messages exchanged by this session's resources.
*
* @throws IllegalStateException If this session is not transacted, an exception will be thrown.
*/
- public void txCommit() throws IllegalStateException;
+ public void txCommit(Option ... options) throws IllegalStateException;
/**
* Roll back the receipt and delivery of all messages exchanged by this session's resources.
*
* @throws IllegalStateException If this session is not transacted, an exception will be thrown.
*/
- public void txRollback() throws IllegalStateException;
+ public void txRollback(Option ... options) throws IllegalStateException;
//---------------------------------------------
// Queue methods
@@ -423,7 +373,7 @@ public interface Session
* declaring connection closes.
* <li> {@link Option#PASSIVE}: <p> If set, the server will not create the queue.
* This field allows the client to assert the presence of a queue without modifying the server state.
- * <li>{@link Option#NO_OPTION}: <p> Has no effect as it represents an �empty� option.
+ * <li>{@link Option#NONE}: <p> Has no effect as it represents an empty option.
* </ul>
* <p>In the absence of a particular option, the defaul value is false for each option
*
@@ -435,7 +385,7 @@ public interface Session
* the queue. </ol>
* @param arguments Used for backward compatibility
* @param options Set of Options ( valide options are: {@link Option#AUTO_DELETE}, {@link Option#DURABLE},
- * {@link Option#EXCLUSIVE}, {@link Option#PASSIVE} and {@link Option#NO_OPTION})
+ * {@link Option#EXCLUSIVE}, {@link Option#PASSIVE} and {@link Option#NONE})
* @see Option
*/
public void queueDeclare(String queueName, String alternateExchange, Map<String, Object> arguments,
@@ -456,7 +406,8 @@ public interface Session
* routing keys depends on the exchange implementation.
* @param arguments Used for backward compatibility
*/
- public void exchangeBind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments);
+ public void exchangeBind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments,
+ Option ... options);
/**
* Unbind a queue from an exchange.
@@ -465,7 +416,7 @@ public interface Session
* @param exchangeName The name of the exchange to unbind from.
* @param routingKey Specifies the routing key of the binding to unbind.
*/
- public void exchangeUnbind(String queueName, String exchangeName, String routingKey);
+ public void exchangeUnbind(String queueName, String exchangeName, String routingKey, Option ... options);
/**
* This method removes all messages from a queue. It does not cancel consumers. Purged messages
@@ -474,7 +425,7 @@ public interface Session
* @param queueName Specifies the name of the queue to purge. If the queue name is empty, refers to the
* current queue for the session, which is the last declared queue.
*/
- public void queuePurge(String queueName);
+ public void queuePurge(String queueName, Option ... options);
/**
* This method deletes a queue. When a queue is deleted any pending messages are sent to a
@@ -485,7 +436,7 @@ public interface Session
* <li> {@link Option#IF_EMPTY}: <p> If set, the server will only delete the queue if it has no messages.
* <li> {@link Option#IF_UNUSED}: <p> If set, the server will only delete the queue if it has no consumers.
* If the queue has consumers the server does does not delete it but raises a channel exception instead.
- * <li>{@link Option#NO_OPTION}: <p> Has no effect as it represents an �empty� option.
+ * <li>{@link Option#NONE}: <p> Has no effect as it represents an empty option.
* </ul>
* </p>
* <p/>
@@ -494,7 +445,7 @@ public interface Session
* @param queueName Specifies the name of the queue to delete. If the queue name is empty, refers to the
* current queue for the session, which is the last declared queue.
* @param options Set of options (Valid options are: {@link Option#IF_EMPTY}, {@link Option#IF_UNUSED}
- * and {@link Option#NO_OPTION})
+ * and {@link Option#NONE})
* @see Option
*/
public void queueDelete(String queueName, Option... options);
@@ -506,7 +457,7 @@ public interface Session
* @param queueName The name of the queue for which information is requested.
* @return Information on the specified queue.
*/
- public Future<QueueQueryResult> queueQuery(String queueName);
+ public Future<QueueQueryResult> queueQuery(String queueName, Option ... options);
/**
@@ -519,7 +470,7 @@ public interface Session
* @return Information on the specified binding.
*/
public Future<ExchangeBoundResult> exchangeBound(String exchange, String queue, String routingKey,
- Map<String, Object> arguments);
+ Map<String, Object> arguments, Option ... options);
// --------------------------------------
// exhcange methods
@@ -536,7 +487,7 @@ public interface Session
* exchanges) are purged when a server restarts.
* <li>{@link Option#PASSIVE}: <p>If set, the server will not create the exchange.
* The client can use this to check whether an exchange exists without modifying the server state.
- * <li> {@link Option#NO_OPTION}: <p>This option is an empty option, and has no effect.
+ * <li> {@link Option#NONE}: <p>This option is an empty option, and has no effect.
* </ul>
* <p>In the absence of a particular option, the defaul value is false for each option</p>
*
@@ -548,7 +499,7 @@ public interface Session
* @param alternateExchange In the event that a message cannot be routed, this is the name of the exchange to which
* the message will be sent.
* @param options Set of options (valid options are: {@link Option#AUTO_DELETE}, {@link Option#DURABLE},
- * {@link Option#PASSIVE}, {@link Option#NO_OPTION})
+ * {@link Option#PASSIVE}, {@link Option#NONE})
* @param arguments Used for backward compatibility
* @see Option
*/
@@ -563,12 +514,12 @@ public interface Session
* <li> {@link Option#IF_UNUSED}: <p> If set, the server will only delete the exchange if it has no queue bindings. If the
* exchange has queue bindings the server does not delete it but raises a channel exception
* instead.
- * <li> {@link Option#NO_OPTION}: <p> Has no effect as it represents an empty option.
+ * <li> {@link Option#NONE}: <p> Has no effect as it represents an empty option.
* </ul>
* <p>Note that if an option is not set, it will default to false.
*
* @param exchangeName The name of exchange to be deleted.
- * @param options Set of options. Valid options are: {@link Option#IF_UNUSED}, {@link Option#NO_OPTION}.
+ * @param options Set of options. Valid options are: {@link Option#IF_UNUSED}, {@link Option#NONE}.
* @see Option
*/
public void exchangeDelete(String exchangeName, Option... options);
@@ -581,7 +532,7 @@ public interface Session
* return information about the default exchange.
* @return Information on the specified exchange.
*/
- public Future<ExchangeQueryResult> exchangeQuery(String exchangeName);
+ public Future<ExchangeQueryResult> exchangeQuery(String exchangeName, Option ... options);
/**
* If the session receives a sessionClosed with an error code it
diff --git a/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSession.java b/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSession.java
new file mode 100644
index 0000000000..27805a1f39
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSession.java
@@ -0,0 +1,142 @@
+package org.apache.qpid.nclient.impl;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.ClosedListener;
+import org.apache.qpid.nclient.MessagePartListener;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Option;
+import org.apache.qpid.transport.Range;
+import org.apache.qpid.transport.RangeSet;
+
+import static org.apache.qpid.transport.Option.*;
+
+/**
+ * Implements a Qpid Sesion.
+ */
+public class ClientSession extends org.apache.qpid.transport.Session implements org.apache.qpid.nclient.DtxSession
+{
+ static
+ {
+ String max = "message_size_before_sync"; // KB's
+ try
+ {
+ MAX_NOT_SYNC_DATA_LENGH = new Long(System.getProperties().getProperty(max, "200000000"));
+ }
+ catch (NumberFormatException e)
+ {
+ // use default size
+ MAX_NOT_SYNC_DATA_LENGH = 200000000;
+ }
+ String flush = "message_size_before_flush";
+ try
+ {
+ MAX_NOT_FLUSH_DATA_LENGH = new Long(System.getProperties().getProperty(flush, "2000000"));
+ }
+ catch (NumberFormatException e)
+ {
+ // use default size
+ MAX_NOT_FLUSH_DATA_LENGH = 20000000;
+ }
+ }
+
+ private static long MAX_NOT_SYNC_DATA_LENGH;
+ private static long MAX_NOT_FLUSH_DATA_LENGH;
+
+ private Map<String,MessagePartListener> _messageListeners = new ConcurrentHashMap<String,MessagePartListener>();
+ private ClosedListener _exceptionListner;
+ private RangeSet _rejectedMessages;
+ private long _currentDataSizeNotSynced;
+ private long _currentDataSizeNotFlushed;
+
+ public ClientSession(byte[] name)
+ {
+ super(name);
+ }
+
+ public void messageAcknowledge(RangeSet ranges, boolean accept)
+ {
+ for (Range range : ranges)
+ {
+ super.processed(range);
+ }
+ super.flushProcessed(accept ? BATCH : NONE);
+ if (accept)
+ {
+ messageAccept(ranges);
+ }
+ }
+
+ public void messageSubscribe(String queue, String destination, short acceptMode, short acquireMode, MessagePartListener listener, Map<String, Object> filter, Option... options)
+ {
+ setMessageListener(destination,listener);
+ super.messageSubscribe(queue, destination, MessageAcceptMode.get(acceptMode),
+ MessageAcquireMode.get(acquireMode), null, 0, filter,
+ options);
+ }
+
+ public void messageTransfer(String destination, Message msg, short acceptMode, short acquireMode) throws IOException
+ {
+ DeliveryProperties dp = msg.getDeliveryProperties();
+ MessageProperties mp = msg.getMessageProperties();
+ ByteBuffer body = msg.readData();
+ int size = body.remaining();
+ super.messageTransfer
+ (destination, MessageAcceptMode.get(acceptMode),
+ MessageAcquireMode.get(acquireMode),
+ new Header(dp, mp), body);
+ _currentDataSizeNotSynced += size;
+ _currentDataSizeNotFlushed += size;
+ }
+
+ public void sync()
+ {
+ super.sync();
+ _currentDataSizeNotSynced = 0;
+ }
+
+ public RangeSet getRejectedMessages()
+ {
+ return _rejectedMessages;
+ }
+
+ public void setMessageListener(String destination, MessagePartListener listener)
+ {
+ if (listener == null)
+ {
+ throw new IllegalArgumentException("Cannot set message listener to null");
+ }
+ _messageListeners.put(destination, listener);
+ }
+
+ public void setClosedListener(ClosedListener exceptionListner)
+ {
+ _exceptionListner = exceptionListner;
+ }
+
+ void setRejectedMessages(RangeSet rejectedMessages)
+ {
+ _rejectedMessages = rejectedMessages;
+ }
+
+ void notifyException(QpidException ex)
+ {
+ _exceptionListner.onClosed(null, null, null);
+ }
+
+ Map<String,MessagePartListener> getMessageListeners()
+ {
+ return _messageListeners;
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSessionDelegate.java b/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSessionDelegate.java
new file mode 100644
index 0000000000..620cf14c33
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/nclient/impl/ClientSessionDelegate.java
@@ -0,0 +1,47 @@
+package org.apache.qpid.nclient.impl;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.ErrorCode;
+
+import org.apache.qpid.nclient.MessagePartListener;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageReject;
+import org.apache.qpid.transport.MessageTransfer;
+import org.apache.qpid.transport.Range;
+import org.apache.qpid.transport.Session;
+import org.apache.qpid.transport.SessionDetached;
+import org.apache.qpid.transport.SessionDelegate;
+
+
+public class ClientSessionDelegate extends SessionDelegate
+{
+
+ // --------------------------------------------
+ // Message methods
+ // --------------------------------------------
+ @Override public void messageTransfer(Session session, MessageTransfer xfr)
+ {
+ MessagePartListener listener = ((ClientSession)session).getMessageListeners()
+ .get(xfr.getDestination());
+ listener.messageTransfer(xfr);
+ }
+
+ @Override public void messageReject(Session session, MessageReject struct)
+ {
+ for (Range range : struct.getTransfers())
+ {
+ for (long l = range.getLower(); l <= range.getUpper(); l++)
+ {
+ System.out.println("message rejected: " +
+ session.getCommand((int) l));
+ }
+ }
+ ((ClientSession)session).setRejectedMessages(struct.getTransfers());
+ ((ClientSession)session).notifyException(new QpidException("Message Rejected",ErrorCode.MESSAGE_REJECTED,null));
+ session.processed(struct);
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/Constants.java b/java/client/src/main/java/org/apache/qpid/nclient/impl/Constants.java
index 83d491baad..f689e9abde 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/Constants.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/impl/Constants.java
@@ -19,7 +19,7 @@
*
*/
-package org.apache.qpidity.nclient.impl;
+package org.apache.qpid.nclient.impl;
/**
* This class holds all the 0.10 client constants which value can be set
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java b/java/client/src/main/java/org/apache/qpid/nclient/impl/DemoClient.java
index 05b99a3cf1..88b5dc6392 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/impl/DemoClient.java
@@ -1,18 +1,20 @@
-package org.apache.qpidity.nclient.impl;
+package org.apache.qpid.nclient.impl;
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.ClosedListener;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
-import org.apache.qpidity.transport.MessageProperties;
+import org.apache.qpid.ErrorCode;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.ClosedListener;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageProperties;
+import java.nio.ByteBuffer;
import java.util.UUID;
public class DemoClient
@@ -56,17 +58,15 @@ public class DemoClient
ssn.messageSubscribe("queue1", "myDest", (short)0, (short)0,createAdapter(), null);
// queue
- ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED);
- ssn.header(new DeliveryProperties().setRoutingKey("queue1"),
- new MessageProperties().setMessageId(UUID.randomUUID()));
- ssn.data("this is the data");
- ssn.endData();
+ ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey("queue1"),
+ new MessageProperties().setMessageId(UUID.randomUUID())),
+ ByteBuffer.wrap("this is the data".getBytes()));
//reject
- ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED);
- ssn.data("this should be rejected");
- ssn.header(new DeliveryProperties().setRoutingKey("stocks"));
- ssn.endData();
+ ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey("stocks")),
+ ByteBuffer.wrap("this should be rejected".getBytes()));
ssn.sync();
// topic subs
@@ -84,11 +84,10 @@ public class DemoClient
ssn.sync();
// topic
- ssn.messageTransfer("amq.topic", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED);
- ssn.data("Topic message");
- ssn.header(new DeliveryProperties().setRoutingKey("stock.us.ibm"),
- new MessageProperties().setMessageId(UUID.randomUUID()));
- ssn.endData();
+ ssn.messageTransfer("amq.topic", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey("stock.us.ibm"),
+ new MessageProperties().setMessageId(UUID.randomUUID())),
+ ByteBuffer.wrap("Topic message".getBytes()));
}
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java b/java/client/src/main/java/org/apache/qpid/nclient/interop/BasicInteropTest.java
index e452091622..9ea9297e14 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/interop/BasicInteropTest.java
@@ -1,24 +1,26 @@
-package org.apache.qpidity.nclient.interop;
+package org.apache.qpid.nclient.interop;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.ClosedListener;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
-import org.apache.qpidity.transport.MessageCreditUnit;
-import org.apache.qpidity.transport.MessageFlowMode;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.RangeSet;
+import org.apache.qpid.ErrorCode;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.api.Message;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.ClosedListener;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageCreditUnit;
+import org.apache.qpid.transport.MessageFlowMode;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.RangeSet;
public class BasicInteropTest implements ClosedListener
{
@@ -77,18 +79,15 @@ public class BasicInteropTest implements ClosedListener
public void testSendMessage(){
System.out.println("------- Sending a message --------");
- session.messageTransfer("test", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED);
-
Map<String,Object> props = new HashMap<String,Object>();
props.put("name", "rajith");
props.put("age", 10);
props.put("spf", 8.5);
- session.header(new DeliveryProperties().setRoutingKey("testKey"),new MessageProperties().setApplicationHeaders(props));
-
- //session.header(new DeliveryProperties().setRoutingKey("testKey"));
+ session.messageTransfer("test", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties().setRoutingKey("testKey"),
+ new MessageProperties().setApplicationHeaders(props)),
+ ByteBuffer.wrap("TestMessage".getBytes()));
- session.data("TestMessage");
- session.endData();
session.sync();
System.out.println("------- Message sent --------");
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/ByteBufferMessage.java b/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java
index 833f905b58..64c89c960c 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/ByteBufferMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/ByteBufferMessage.java
@@ -1,14 +1,13 @@
-package org.apache.qpidity.nclient.util;
+package org.apache.qpid.nclient.util;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.Queue;
+import java.util.*;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.api.Message;
/**
* <p>A Simple implementation of the message interface
@@ -22,7 +21,7 @@ import org.apache.qpidity.api.Message;
*/
public class ByteBufferMessage implements Message
{
- private Queue<ByteBuffer> _data = new LinkedList<ByteBuffer>();
+ private List<ByteBuffer> _data;// = new ArrayList<ByteBuffer>();
private ByteBuffer _readBuffer;
private int _dataSize;
private DeliveryProperties _currentDeliveryProps;
@@ -30,6 +29,12 @@ public class ByteBufferMessage implements Message
private int _transferId;
private Header _header;
+ public ByteBufferMessage(MessageProperties messageProperties, DeliveryProperties deliveryProperties)
+ {
+ _currentMessageProps = messageProperties;
+ _currentDeliveryProps = deliveryProperties;
+ }
+
public void setHeader(Header header) {
_header = header;
}
@@ -70,7 +75,18 @@ public class ByteBufferMessage implements Message
*/
public void appendData(ByteBuffer src) throws IOException
{
- _data.offer(src);
+ if(_data == null)
+ {
+ _data = Collections.singletonList(src);
+ }
+ else
+ {
+ if(_data.size() == 1)
+ {
+ _data = new ArrayList<ByteBuffer>(_data);
+ }
+ _data.add(src);
+ }
_dataSize += src.remaining();
}
@@ -94,12 +110,12 @@ public class ByteBufferMessage implements Message
_currentMessageProps = props;
}
- public void readData(byte[] target) throws IOException
+ public void readData(byte[] target)
{
getReadBuffer().get(target);
}
- public ByteBuffer readData() throws IOException
+ public ByteBuffer readData()
{
return getReadBuffer();
}
@@ -109,7 +125,7 @@ public class ByteBufferMessage implements Message
//optimize for the simple cases
if(_data.size() == 1)
{
- _readBuffer = _data.element().duplicate();
+ _readBuffer = _data.get(0).duplicate();
}
else
{
@@ -122,7 +138,7 @@ public class ByteBufferMessage implements Message
}
}
- private ByteBuffer getReadBuffer() throws IOException
+ private ByteBuffer getReadBuffer()
{
if (_readBuffer != null )
{
@@ -137,7 +153,7 @@ public class ByteBufferMessage implements Message
}
else
{
- throw new IOException("No Data to read");
+ return ByteBuffer.allocate(0);
}
}
}
@@ -145,16 +161,9 @@ public class ByteBufferMessage implements Message
//hack for testing
@Override public String toString()
{
- try
- {
- ByteBuffer temp = getReadBuffer();
- byte[] b = new byte[temp.remaining()];
- temp.get(b);
- return new String(b);
- }
- catch(IOException e)
- {
- return "No data";
- }
+ ByteBuffer temp = getReadBuffer();
+ byte[] b = new byte[temp.remaining()];
+ temp.get(b);
+ return new String(b);
}
}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/FileMessage.java b/java/client/src/main/java/org/apache/qpid/nclient/util/FileMessage.java
index 289d03574d..179c91c2e9 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/FileMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/FileMessage.java
@@ -1,4 +1,4 @@
-package org.apache.qpidity.nclient.util;
+package org.apache.qpid.nclient.util;
import java.io.EOFException;
import java.io.FileInputStream;
@@ -7,10 +7,10 @@ import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.api.Message;
/**
* FileMessage provides pull style semantics for
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/MessageListener.java b/java/client/src/main/java/org/apache/qpid/nclient/util/MessageListener.java
index 43c20eb6b5..c5edd62143 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/MessageListener.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/MessageListener.java
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.nclient.util;
+package org.apache.qpid.nclient.util;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.api.Message;
/**
*A message listener
diff --git a/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java
new file mode 100644
index 0000000000..0e54e04a99
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/MessagePartListenerAdapter.java
@@ -0,0 +1,67 @@
+package org.apache.qpid.nclient.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.*;
+import org.apache.qpid.nclient.MessagePartListener;
+
+/**
+ * This is a simple message assembler.
+ * Will call onMessage method of the adaptee
+ * when all message data is read.
+ *
+ * This is a good convinience utility for handling
+ * small messages
+ */
+public class MessagePartListenerAdapter implements MessagePartListener
+{
+ MessageListener _adaptee;
+ ByteBufferMessage _currentMsg;
+
+ public MessagePartListenerAdapter(MessageListener listener)
+ {
+ _adaptee = listener;
+ }
+
+ public void messageTransfer(MessageTransfer xfr)
+ {
+ _currentMsg = new ByteBufferMessage(xfr.getId());
+
+ for (Struct st : xfr.getHeader().getStructs())
+ {
+ if(st instanceof DeliveryProperties)
+ {
+ _currentMsg.setDeliveryProperties((DeliveryProperties)st);
+
+ }
+ else if(st instanceof MessageProperties)
+ {
+ _currentMsg.setMessageProperties((MessageProperties)st);
+ }
+
+ }
+
+
+ ByteBuffer body = xfr.getBody();
+ if (body == null)
+ {
+ body = ByteBuffer.allocate(0);
+ }
+
+
+ try
+ {
+ _currentMsg.appendData(body);
+ }
+ catch(IOException e)
+ {
+ // A chance for IO exception
+ // doesn't occur as we are using
+ // a ByteBuffer
+ }
+
+ _adaptee.onMessage(_currentMsg);
+ }
+
+}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/ReadOnlyMessage.java b/java/client/src/main/java/org/apache/qpid/nclient/util/ReadOnlyMessage.java
index 8ff5c62a25..6583a95c7e 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/ReadOnlyMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/ReadOnlyMessage.java
@@ -1,10 +1,10 @@
-package org.apache.qpidity.nclient.util;
+package org.apache.qpid.nclient.util;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.api.Message;
public abstract class ReadOnlyMessage implements Message
{
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/StreamingMessage.java b/java/client/src/main/java/org/apache/qpid/nclient/util/StreamingMessage.java
index 6c7f9e9db7..a4574438ac 100644
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/StreamingMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/nclient/util/StreamingMessage.java
@@ -1,14 +1,14 @@
-package org.apache.qpidity.nclient.util;
+package org.apache.qpid.nclient.util;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.api.Message;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.api.Message;
public class StreamingMessage extends ReadOnlyMessage implements Message
{
diff --git a/java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.java b/java/client/src/main/java/org/apache/qpid/njms/ExceptionHelper.java
index e00f9008d3..ce790a3b24 100644
--- a/java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.java
+++ b/java/client/src/main/java/org/apache/qpid/njms/ExceptionHelper.java
@@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.njms;
+package org.apache.qpid.njms;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import javax.jms.JMSException;
import javax.transaction.xa.XAException;
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java
deleted file mode 100644
index f7d54a681f..0000000000
--- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package org.apache.qpidity.nclient.impl;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.ClosedListener;
-import org.apache.qpidity.nclient.MessagePartListener;
-import org.apache.qpidity.transport.MessageAcceptMode;
-import org.apache.qpidity.transport.MessageAcquireMode;
-import org.apache.qpidity.transport.Option;
-import org.apache.qpidity.transport.Range;
-import org.apache.qpidity.transport.RangeSet;
-
-/**
- * Implements a Qpid Sesion.
- */
-public class ClientSession extends org.apache.qpidity.transport.Session implements org.apache.qpidity.nclient.DtxSession
-{
- static
- {
- String max = "message_size_before_sync"; // KB's
- try
- {
- MAX_NOT_SYNC_DATA_LENGH = new Long(System.getProperties().getProperty(max, "200000000"));
- }
- catch (NumberFormatException e)
- {
- // use default size
- MAX_NOT_SYNC_DATA_LENGH = 200000000;
- }
- String flush = "message_size_before_flush";
- try
- {
- MAX_NOT_FLUSH_DATA_LENGH = new Long(System.getProperties().getProperty(flush, "2000000"));
- }
- catch (NumberFormatException e)
- {
- // use default size
- MAX_NOT_FLUSH_DATA_LENGH = 20000000;
- }
- }
-
- private static long MAX_NOT_SYNC_DATA_LENGH;
- private static long MAX_NOT_FLUSH_DATA_LENGH;
-
- private Map<String,MessagePartListener> _messageListeners = new ConcurrentHashMap<String,MessagePartListener>();
- private ClosedListener _exceptionListner;
- private RangeSet _rejectedMessages;
- private long _currentDataSizeNotSynced;
- private long _currentDataSizeNotFlushed;
-
- public ClientSession(byte[] name)
- {
- super(name);
- }
-
- public void messageAcknowledge(RangeSet ranges, boolean accept)
- {
- for (Range range : ranges)
- {
- super.processed(range);
- }
- super.flushProcessed();
- if( accept )
- {
- messageAccept(ranges);
- }
- }
-
- public void messageSubscribe(String queue, String destination, short acceptMode, short acquireMode, MessagePartListener listener, Map<String, Object> filter, Option... options)
- {
- setMessageListener(destination,listener);
- super.messageSubscribe(queue, destination, MessageAcceptMode.get(acceptMode),
- MessageAcquireMode.get(acquireMode), null, 0, filter,
- options);
- }
-
- public void messageTransfer(String destination, Message msg, short acceptMode, short acquireMode) throws IOException
- {
- // The javadoc clearly says that this method is suitable for small messages
- // therefore reading the content in one shot.
- ByteBuffer data = msg.readData();
- super.messageTransfer(destination, MessageAcceptMode.get(acceptMode),
- MessageAcquireMode.get(acquireMode));
- // super.header(msg.getDeliveryProperties(),msg.getMessageProperties() );
- if( msg.getHeader() == null || msg.getDeliveryProperties().isDirty() || msg.getMessageProperties().isDirty() )
- {
- msg.setHeader( super.header(msg.getDeliveryProperties(),msg.getMessageProperties()) );
- msg.getDeliveryProperties().setDirty(false);
- msg.getMessageProperties().setDirty(false);
- }
- else
- {
- super.header(msg.getHeader());
- }
- data( data );
- endData();
- }
-
- public void sync()
- {
- super.sync();
- _currentDataSizeNotSynced = 0;
- }
-
- /* -------------------------
- * Data methods
- * ------------------------*/
-
- public void data(ByteBuffer buf)
- {
- _currentDataSizeNotSynced = _currentDataSizeNotSynced + buf.remaining();
- _currentDataSizeNotFlushed = _currentDataSizeNotFlushed + buf.remaining();
- super.data(buf);
- }
-
- public void data(String str)
- {
- _currentDataSizeNotSynced = _currentDataSizeNotSynced + str.getBytes().length;
- super.data(str);
- }
-
- public void data(byte[] bytes)
- {
- _currentDataSizeNotSynced = _currentDataSizeNotSynced + bytes.length;
- super.data(bytes);
- }
-
- public void messageStream(String destination, Message msg, short acceptMode, short acquireMode) throws IOException
- {
- super.messageTransfer(destination, MessageAcceptMode.get(acceptMode),
- MessageAcquireMode.get(acquireMode));
- super.header(msg.getDeliveryProperties(),msg.getMessageProperties());
- boolean b = true;
- int count = 0;
- while(b)
- {
- try
- {
- System.out.println("count : " + count++);
- data(msg.readData());
- }
- catch(EOFException e)
- {
- b = false;
- }
- }
- endData();
- }
-
- public void endData()
- {
- super.endData();
- /* if( MAX_NOT_SYNC_DATA_LENGH != -1 && _currentDataSizeNotSynced >= MAX_NOT_SYNC_DATA_LENGH)
- {
- sync();
- }
- if( MAX_NOT_FLUSH_DATA_LENGH != -1 && _currentDataSizeNotFlushed >= MAX_NOT_FLUSH_DATA_LENGH)
- {
- executionFlush();
- _currentDataSizeNotFlushed = 0;
- }*/
- }
-
- public RangeSet getRejectedMessages()
- {
- return _rejectedMessages;
- }
-
- public void setMessageListener(String destination, MessagePartListener listener)
- {
- if (listener == null)
- {
- throw new IllegalArgumentException("Cannot set message listener to null");
- }
- _messageListeners.put(destination, listener);
- }
-
- public void setClosedListener(ClosedListener exceptionListner)
- {
- _exceptionListner = exceptionListner;
- }
-
- void setRejectedMessages(RangeSet rejectedMessages)
- {
- _rejectedMessages = rejectedMessages;
- }
-
- void notifyException(QpidException ex)
- {
- _exceptionListner.onClosed(null, null, null);
- }
-
- Map<String,MessagePartListener> getMessageListeners()
- {
- return _messageListeners;
- }
-}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java
deleted file mode 100644
index e57dd08448..0000000000
--- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.apache.qpidity.nclient.impl;
-
-import java.nio.ByteBuffer;
-
-import org.apache.qpidity.ErrorCode;
-
-import org.apache.qpidity.nclient.MessagePartListener;
-
-import org.apache.qpidity.QpidException;
-import org.apache.qpidity.transport.Data;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.transport.MessageReject;
-import org.apache.qpidity.transport.MessageTransfer;
-import org.apache.qpidity.transport.Range;
-import org.apache.qpidity.transport.Session;
-import org.apache.qpidity.transport.SessionDetached;
-import org.apache.qpidity.transport.SessionDelegate;
-
-
-public class ClientSessionDelegate extends SessionDelegate
-{
- private MessageTransfer _currentTransfer;
- private MessagePartListener _currentMessageListener;
-
- @Override public void sessionDetached(Session ssn, SessionDetached dtc)
- {
- ((ClientSession)ssn).notifyException(new QpidException("", ErrorCode.get(dtc.getCode().getValue()),null));
- }
-
- // --------------------------------------------
- // Message methods
- // --------------------------------------------
- @Override public void data(Session ssn, Data data)
- {
- for (ByteBuffer b : data.getFragments())
- {
- _currentMessageListener.data(b);
- }
- if (data.isLast())
- {
- _currentMessageListener.messageReceived();
- }
-
- }
-
- @Override public void header(Session ssn, Header header)
- {
- _currentMessageListener.messageHeader(header);
- if( header.hasNoPayload())
- {
- _currentMessageListener.data(ByteBuffer.allocate(0));
- _currentMessageListener.messageReceived();
- }
- }
-
-
- @Override public void messageTransfer(Session session, MessageTransfer currentTransfer)
- {
- _currentTransfer = currentTransfer;
- _currentMessageListener = ((ClientSession)session).getMessageListeners().get(currentTransfer.getDestination());
- _currentMessageListener.messageTransfer(currentTransfer.getId());
- }
-
- @Override public void messageReject(Session session, MessageReject struct)
- {
- for (Range range : struct.getTransfers())
- {
- for (long l = range.getLower(); l <= range.getUpper(); l++)
- {
- System.out.println("message rejected: " +
- session.getCommand((int) l));
- }
- }
- ((ClientSession)session).setRejectedMessages(struct.getTransfers());
- ((ClientSession)session).notifyException(new QpidException("Message Rejected",ErrorCode.MESSAGE_REJECTED,null));
- session.processed(struct);
- }
-
-}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java
deleted file mode 100644
index 64ffe17fe0..0000000000
--- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.apache.qpidity.nclient.impl;
-
-import java.io.FileInputStream;
-
-import org.apache.qpidity.ErrorCode;
-import org.apache.qpidity.api.Message;
-import org.apache.qpidity.nclient.Client;
-import org.apache.qpidity.nclient.Connection;
-import org.apache.qpidity.nclient.ClosedListener;
-import org.apache.qpidity.nclient.Session;
-import org.apache.qpidity.nclient.util.FileMessage;
-import org.apache.qpidity.nclient.util.MessageListener;
-import org.apache.qpidity.nclient.util.MessagePartListenerAdapter;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-
-import java.util.UUID;
-
-public class LargeMsgDemoClient
-{
- public static MessagePartListenerAdapter createAdapter()
- {
- return new MessagePartListenerAdapter(new MessageListener()
- {
- public void onMessage(Message m)
- {
- System.out.println("\n================== Received Msg ==================");
- System.out.println("Message Id : " + m.getMessageProperties().getMessageId());
- System.out.println(m.toString());
- System.out.println("================== End Msg ==================\n");
- }
-
- });
- }
-
- public static final void main(String[] args)
- {
- Connection conn = Client.createConnection();
- try{
- conn.connect("0.0.0.0", 5672, "test", "guest", "guest");
- }catch(Exception e){
- e.printStackTrace();
- }
-
- Session ssn = conn.createSession(50000);
- ssn.setClosedListener(new ClosedListener()
- {
- public void onClosed(ErrorCode errorCode, String reason, Throwable t)
- {
- System.out.println("ErrorCode : " + errorCode + " reason : " + reason);
- }
- });
- ssn.queueDeclare("queue1", null, null);
- ssn.exchangeBind("queue1", "amq.direct", "queue1",null);
- ssn.sync();
-
- ssn.messageSubscribe("queue1", "myDest", (short)0, (short)0,createAdapter(), null);
-
- try
- {
- FileMessage msg = new FileMessage(new FileInputStream("/home/rajith/TestFile"),
- 1024,
- new DeliveryProperties().setRoutingKey("queue1"),
- new MessageProperties().setMessageId(UUID.randomUUID()));
-
- // queue
- ssn.messageStream("amq.direct",msg, (short) 0, (short) 1);
- ssn.sync();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
-
-}
diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/util/MessagePartListenerAdapter.java b/java/client/src/main/java/org/apache/qpidity/nclient/util/MessagePartListenerAdapter.java
deleted file mode 100644
index 757d44fbbb..0000000000
--- a/java/client/src/main/java/org/apache/qpidity/nclient/util/MessagePartListenerAdapter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.apache.qpidity.nclient.util;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.nclient.MessagePartListener;
-
-/**
- * This is a simple message assembler.
- * Will call onMessage method of the adaptee
- * when all message data is read.
- *
- * This is a good convinience utility for handling
- * small messages
- */
-public class MessagePartListenerAdapter implements MessagePartListener
-{
- MessageListener _adaptee;
- ByteBufferMessage _currentMsg;
-
- public MessagePartListenerAdapter(MessageListener listener)
- {
- _adaptee = listener;
- }
-
- public void messageTransfer(int transferId)
- {
- _currentMsg = new ByteBufferMessage(transferId);
- }
-
- public void data(ByteBuffer src)
- {
- try
- {
- _currentMsg.appendData(src);
- }
- catch(IOException e)
- {
- // A chance for IO exception
- // doesn't occur as we are using
- // a ByteBuffer
- }
- }
-
- public void messageHeader(Header header)
- {
- _currentMsg.setDeliveryProperties(header.get(DeliveryProperties.class));
- _currentMsg.setMessageProperties(header.get(MessageProperties.class));
- }
-
- public void messageReceived()
- {
- _adaptee.onMessage(_currentMsg);
- }
-
-}
diff --git a/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java b/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
new file mode 100644
index 0000000000..5323ad28bf
--- /dev/null
+++ b/java/client/src/test/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.mina.transport.vmpipe.support;
+
+import org.apache.mina.common.IdleStatus;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This file is a patch to override MINA, because of the IdentityHashMap bug. Workaround to be supplied in MINA 1.0.7.
+ * This patched file will be removed once upgraded onto a newer MINA.
+ *
+ * Dectects idle sessions and fires <tt>sessionIdle</tt> events to them.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class VmPipeIdleStatusChecker
+{
+ private static final VmPipeIdleStatusChecker INSTANCE = new VmPipeIdleStatusChecker();
+
+ public static VmPipeIdleStatusChecker getInstance()
+ {
+ return INSTANCE;
+ }
+
+ private final Map sessions = new HashMap(); // will use as a set
+
+ private final Worker worker = new Worker();
+
+ private VmPipeIdleStatusChecker()
+ {
+ worker.start();
+ }
+
+ public void addSession(VmPipeSessionImpl session)
+ {
+ synchronized (sessions)
+ {
+ sessions.put(session, session);
+ }
+ }
+
+ private class Worker extends Thread
+ {
+ private Worker()
+ {
+ super("VmPipeIdleStatusChecker");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ for (;;)
+ {
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ { }
+
+ long currentTime = System.currentTimeMillis();
+
+ synchronized (sessions)
+ {
+ Iterator it = sessions.keySet().iterator();
+ while (it.hasNext())
+ {
+ VmPipeSessionImpl session = (VmPipeSessionImpl) it.next();
+ if (!session.isConnected())
+ {
+ it.remove();
+ }
+ else
+ {
+ notifyIdleSession(session, currentTime);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyIdleSession(VmPipeSessionImpl session, long currentTime)
+ {
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE,
+ Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE,
+ Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE)));
+ }
+
+ private void notifyIdleSession0(VmPipeSessionImpl session, long currentTime, long idleTime, IdleStatus status,
+ long lastIoTime)
+ {
+ if ((idleTime > 0) && (lastIoTime != 0) && ((currentTime - lastIoTime) >= idleTime))
+ {
+ session.increaseIdleCount(status);
+ session.getFilterChain().fireSessionIdle(session, status);
+ }
+ }
+
+}
diff --git a/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java b/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
index 9b477c19e2..7ee991b63c 100644
--- a/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
+++ b/java/client/src/test/java/org/apache/qpid/client/message/TestMessageHelper.java
@@ -26,21 +26,21 @@ public class TestMessageHelper
{
public static JMSTextMessage newJMSTextMessage() throws JMSException
{
- return new JMSTextMessage();
+ return new JMSTextMessage(AMQMessageDelegateFactory.FACTORY_0_8);
}
public static JMSBytesMessage newJMSBytesMessage() throws JMSException
{
- return new JMSBytesMessage();
+ return new JMSBytesMessage(AMQMessageDelegateFactory.FACTORY_0_8);
}
public static JMSMapMessage newJMSMapMessage() throws JMSException
{
- return new JMSMapMessage();
+ return new JMSMapMessage(AMQMessageDelegateFactory.FACTORY_0_8);
}
public static JMSStreamMessage newJMSStreamMessage()
{
- return new JMSStreamMessage();
+ return new JMSStreamMessage(AMQMessageDelegateFactory.FACTORY_0_8);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
index b6776a1a44..66f220643c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java
@@ -27,12 +27,10 @@ import org.apache.qpid.AMQInvalidRoutingKeyException;
import org.apache.qpid.client.AMQNoConsumersException;
import org.apache.qpid.client.AMQNoRouteException;
import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ChannelCloseBody;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQMethodEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,12 +46,10 @@ public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListe
return _handler;
}
- public void methodReceived(AMQStateManager stateManager, ChannelCloseBody method, int channelId)
+ public void methodReceived(AMQProtocolSession session, ChannelCloseBody method, int channelId)
throws AMQException
{
_logger.debug("ChannelClose method received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
-
AMQConstant errorCode = AMQConstant.getConstant(method.getReplyCode());
AMQShortString reason = method.getReplyText();
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
index 27adc4dd77..6f4c26945c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
@@ -33,11 +33,12 @@ public class ConnectionURLTest extends TestCase
public void testFailoverURL() throws URLSyntaxException
{
- String url = "amqp://ritchiem:bob@/test?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin'";
+ String url = "amqp://ritchiem:bob@/test?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin?cyclecount='100''";
ConnectionURL connectionurl = new AMQConnectionURL(url);
assertTrue(connectionurl.getFailoverMethod().equals("roundrobin"));
+ assertEquals("100", connectionurl.getFailoverOption(ConnectionURL.OPTIONS_FAILOVER_CYCLE));
assertTrue(connectionurl.getUsername().equals("ritchiem"));
assertTrue(connectionurl.getPassword().equals("bob"));
assertTrue(connectionurl.getVirtualHost().equals("/test"));
@@ -276,7 +277,7 @@ public class ConnectionURLTest extends TestCase
public void testSingleTransportMultiOptionURL() throws URLSyntaxException
{
- String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672',routingkey='jim',timeout='200',immediatedelivery='true'";
+ String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672?foo='jim'&bar='bob'&fred='jimmy'',routingkey='jim',timeout='200',immediatedelivery='true'";
ConnectionURL connectionurl = new AMQConnectionURL(url);
@@ -493,8 +494,38 @@ public class ConnectionURLTest extends TestCase
}
}
+ public void testSingleTransportMultiOptionOnBrokerURL() throws URLSyntaxException
+ {
+ String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672?foo='jim'&bar='bob'&fred='jimmy'',routingkey='jim',timeout='200',immediatedelivery='true'";
+
+ ConnectionURL connectionurl = new AMQConnectionURL(url);
+
+ assertTrue(connectionurl.getFailoverMethod() == null);
+ assertTrue(connectionurl.getUsername().equals("guest"));
+ assertTrue(connectionurl.getPassword().equals("guest"));
+ assertTrue(connectionurl.getVirtualHost().equals("/test"));
+
+ assertTrue(connectionurl.getBrokerCount() == 1);
+
+ BrokerDetails service = connectionurl.getBrokerDetails(0);
+
+ assertTrue(service.getTransport().equals("tcp"));
+
+
+ assertTrue(service.getHost().equals("localhost"));
+ assertTrue(service.getPort() == 5672);
+ assertEquals("jim",service.getProperty("foo"));
+ assertEquals("bob",service.getProperty("bar"));
+ assertEquals("jimmy",service.getProperty("fred"));
+
+ assertTrue(connectionurl.getOption("routingkey").equals("jim"));
+ assertTrue(connectionurl.getOption("timeout").equals("200"));
+ assertTrue(connectionurl.getOption("immediatedelivery").equals("true"));
+ }
+
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(ConnectionURLTest.class);
}
}
+
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java
index 88dd212ab6..2a66b86985 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java
@@ -23,7 +23,6 @@ package org.apache.qpid.test.unit.client.destinationurl;
import junit.framework.TestCase;
import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.test.unit.basic.PropertyValueTest;
import org.apache.qpid.url.AMQBindingURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
index fd425b9930..b5e7ae82b5 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/MessageConverterTest.java
@@ -20,20 +20,20 @@
*/
package org.apache.qpid.test.unit.message;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.MapMessage;
-import javax.jms.Message;
-import javax.jms.TextMessage;
+import javax.jms.*;
import junit.framework.TestCase;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.message.JMSMapMessage;
-import org.apache.qpid.client.message.JMSTextMessage;
-import org.apache.qpid.client.message.MessageConverter;
+import org.apache.qpid.client.*;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.client.message.*;
import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+
+import java.util.Map;
public class MessageConverterTest extends TestCase
@@ -47,36 +47,38 @@ public class MessageConverterTest extends TestCase
protected JMSTextMessage testTextMessage;
protected JMSMapMessage testMapMessage;
+ private AMQSession _session = new TestAMQSession();
+
protected void setUp() throws Exception
{
super.setUp();
- testTextMessage = new JMSTextMessage();
+ testTextMessage = new JMSTextMessage(AMQMessageDelegateFactory.FACTORY_0_8);
//Set Message Text
testTextMessage.setText("testTextMessage text");
setMessageProperties(testTextMessage);
- testMapMessage = new JMSMapMessage();
+ testMapMessage = new JMSMapMessage(AMQMessageDelegateFactory.FACTORY_0_8);
testMapMessage.setString("testMapString", "testMapStringValue");
testMapMessage.setDouble("testMapDouble", Double.MAX_VALUE);
}
public void testSetProperties() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((TextMessage) testTextMessage).getConvertedMessage();
+ AbstractJMSMessage newMessage = new MessageConverter(_session, (TextMessage) testTextMessage).getConvertedMessage();
mesagePropertiesTest(testTextMessage, newMessage);
}
public void testJMSTextMessageConversion() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((TextMessage) testTextMessage).getConvertedMessage();
+ AbstractJMSMessage newMessage = new MessageConverter(_session, (TextMessage) testTextMessage).getConvertedMessage();
assertEquals("Converted message text mismatch", ((JMSTextMessage) newMessage).getText(), testTextMessage.getText());
}
public void testJMSMapMessageConversion() throws Exception
{
- AbstractJMSMessage newMessage = new MessageConverter((MapMessage) testMapMessage).getConvertedMessage();
+ AbstractJMSMessage newMessage = new MessageConverter(_session, (MapMessage) testMapMessage).getConvertedMessage();
assertEquals("Converted map message String mismatch", ((JMSMapMessage) newMessage).getString("testMapString"),
testMapMessage.getString("testMapString"));
assertEquals("Converted map message Double mismatch", ((JMSMapMessage) newMessage).getDouble("testMapDouble"),
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
new file mode 100644
index 0000000000..a881f6a822
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java
@@ -0,0 +1,171 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.unit.message;
+
+import org.apache.qpid.client.*;
+import org.apache.qpid.client.message.AMQMessageDelegateFactory;
+import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
+
+import javax.jms.*;
+import java.util.Map;
+
+public class TestAMQSession extends AMQSession<BasicMessageConsumer_0_8, BasicMessageProducer_0_8>
+{
+
+ public TestAMQSession()
+ {
+ super(null, 0, false, AUTO_ACKNOWLEDGE, null, 0, 0);
+ }
+
+ public void acknowledgeMessage(long deliveryTag, boolean multiple)
+ {
+
+ }
+
+ public void sendQueueBind(AMQShortString queueName, AMQShortString routingKey, FieldTable arguments, AMQShortString exchangeName, AMQDestination destination) throws AMQException, FailoverException
+ {
+
+ }
+
+ public void sendClose(long timeout) throws AMQException, FailoverException
+ {
+
+ }
+
+ public void sendCommit() throws AMQException, FailoverException
+ {
+
+ }
+
+ public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException
+ {
+ return null;
+ }
+
+ public void sendCreateQueue(AMQShortString name, boolean autoDelete, boolean durable, boolean exclusive, Map<String, Object> arguments) throws AMQException, FailoverException
+ {
+
+ }
+
+ public TemporaryQueue createTemporaryQueue() throws JMSException
+ {
+ return null;
+ }
+
+ protected void sendRecover() throws AMQException, FailoverException
+ {
+
+ }
+
+ public void rejectMessage(long deliveryTag, boolean requeue)
+ {
+
+ }
+
+ public void releaseForRollback()
+ {
+
+ }
+
+ public void sendRollback() throws AMQException, FailoverException
+ {
+
+ }
+
+ public BasicMessageConsumer_0_8 createMessageConsumer(AMQDestination destination, int prefetchHigh, int prefetchLow, boolean noLocal, boolean exclusive, String selector, FieldTable arguments, boolean noConsume, boolean autoClose) throws JMSException
+ {
+ return null;
+ }
+
+ public boolean isQueueBound(AMQShortString exchangeName, AMQShortString queueName, AMQShortString routingKey) throws JMSException
+ {
+ return false;
+ }
+
+ public boolean isQueueBound(AMQDestination destination) throws JMSException
+ {
+ return false;
+ }
+
+ public void sendConsume(BasicMessageConsumer_0_8 consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector, int tag) throws AMQException, FailoverException
+ {
+
+ }
+
+ public BasicMessageProducer_0_8 createMessageProducer(Destination destination, boolean mandatory, boolean immediate, boolean waitUntilSent, long producerId)
+ {
+ return null;
+ }
+
+ protected Long requestQueueDepth(AMQDestination amqd) throws AMQException, FailoverException
+ {
+ return null;
+ }
+
+ public void sendExchangeDeclare(AMQShortString name, AMQShortString type, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException, FailoverException
+ {
+
+ }
+
+ public void sendQueueDeclare(AMQDestination amqd, AMQProtocolHandler protocolHandler) throws AMQException, FailoverException
+ {
+
+ }
+
+ public void sendQueueDelete(AMQShortString queueName) throws AMQException, FailoverException
+ {
+
+ }
+
+ public void sendSuspendChannel(boolean suspend) throws AMQException, FailoverException
+ {
+
+ }
+
+ protected boolean tagLE(long tag1, long tag2)
+ {
+ return false;
+ }
+
+ protected boolean updateRollbackMark(long current, long deliveryTag)
+ {
+ return false;
+ }
+
+ public AMQMessageDelegateFactory getMessageDelegateFactory()
+ {
+ return AMQMessageDelegateFactory.FACTORY_0_8;
+ }
+
+ protected Object getFailoverMutex()
+ {
+ return this;
+ }
+
+ public void checkNotClosed()
+ {
+
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/testutil/Config.java b/java/client/src/test/java/org/apache/qpid/testutil/Config.java
deleted file mode 100644
index b777cf93b6..0000000000
--- a/java/client/src/test/java/org/apache/qpid/testutil/Config.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.testutil;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQHeadersExchange;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.exchange.ExchangeDefaults;
-
-public class Config
-{
- public static final String QUEUE = "queue";
- public static final String TOPIC = "topic";
- public static final String HEADERS = "headers";
-
- private String host = "localhost";
- private int port = 5672;
- private String type;
- private String name = "simple_test_queue";
-
- public Config()
- {
- this("localhost", 5672, QUEUE, "simple_test_queue");
- }
-
- public Config(String host, int port, String type, String name)
- {
- setHost(host);
- setPort(port);
- setType(type);
- setName(name);
- }
-
- public String getHost()
- {
- return host;
- }
-
- public void setHost(String host)
- {
- this.host = host;
- }
-
- public int getPort()
- {
- return port;
- }
-
- public void setPort(int port)
- {
- this.port = port;
- }
-
- public String getType()
- {
- return type;
- }
-
- public void setType(String type)
- {
- this.type = type;
- }
-
- public boolean isQueue()
- {
- return QUEUE.equalsIgnoreCase(type);
- }
-
- public boolean isTopic()
- {
- return TOPIC.equalsIgnoreCase(type);
- }
-
- private boolean isHeaders()
- {
- return HEADERS.equalsIgnoreCase(type);
- }
-
- public void setQueue(boolean queue)
- {
- type = queue ? QUEUE : TOPIC;
- }
-
- public String getName()
- {
- return name;
- }
-
- public void setName(String name)
- {
- this.name = name;
- }
-
- public Destination getDestination()
- {
- if(isQueue())
- {
- System.out.println("Using queue named " + name);
- return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME,name);
- }
- else if(isTopic())
- {
- System.out.println("Using topic named " + name);
- return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME,name);
- }
- else if(isHeaders())
- {
- System.out.println("Using headers exhange named " + name);
- return new AMQHeadersExchange(name);
- }
- return null;
- }
-
- public Connection getConnection() throws Exception
- {
- System.out.println("Connecting to " + host + " on " + port + "...");
- return new AMQConnection(host, port, "guest", "guest", "Client" + System.currentTimeMillis(), "/test");
- }
-
- public boolean setOptions(String[] argv)
- {
- try
- {
- for(int i = 0; i < argv.length - 1; i += 2)
- {
- String key = argv[i];
- String value = argv[i+1];
- setOption(key, value);
- }
- return true;
- }
- catch(Exception e)
- {
- System.out.println(e.getMessage());
- }
- return false;
- }
-
- private void setOption(String key, String value)
- {
- if("-host".equalsIgnoreCase(key))
- {
- setHost(value);
- }
- else if("-port".equalsIgnoreCase(key))
- {
- try
- {
- setPort(Integer.parseInt(value));
- }
- catch(NumberFormatException e)
- {
- throw new RuntimeException("Bad port number: " + value, e);
- }
- }
- else if("-name".equalsIgnoreCase(key))
- {
- setName(value);
- }
- else if("-type".equalsIgnoreCase(key))
- {
- if(QUEUE.equalsIgnoreCase(value)
- || TOPIC.equalsIgnoreCase(value)
- || HEADERS.equalsIgnoreCase(value))
- {
- type = value;
- }
- else{
- throw new RuntimeException("Bad destination type: " + value);
- }
- }
- else
- {
- System.out.println("Ignoring unrecognised option: " + key);
- }
- }
-}
diff --git a/java/common.xml b/java/common.xml
index 8d61880714..8606a24edb 100644
--- a/java/common.xml
+++ b/java/common.xml
@@ -47,6 +47,8 @@
<property name="tasks.classes" location="${tasks}/classes"/>
<property name="tasks.src" location="${tasks}/src"/>
+ <property name="javac.compiler.args" value=""/>
+
<macrodef name="indirect">
<attribute name="name"/>
<attribute name="variable"/>
@@ -75,8 +77,9 @@
</macrodef>
<mkdir dir="${tasks.classes}"/>
- <javac srcdir="${tasks.src}" destdir="${tasks.classes}"
- classpath="${java.class.path}"/>
+ <javac source="${java.source}" target="${java.target}" srcdir="${tasks.src}" destdir="${tasks.classes}" classpath="${java.class.path}">
+ <compilerarg line="${javac.compiler.args}"/>
+ </javac>
<taskdef name="map" classname="org.apache.qpid.tasks.Map"
classpath="${tasks.classes}"/>
@@ -118,7 +121,7 @@
${build.bin}
- ant test [ -Dtest=&lt;pattern&gt; ] [ report ]
+ ant test [ -Dtest=&lt;pattern&gt; ] [-Dprofile=&lt;profile&gt;] [ report ]
Execute unit tests and place the output in the build results
directory:
@@ -149,7 +152,9 @@
default to running all available tests for the project or module
depending on the current working directory.
- Finally it can be useful to append the report target in order to
+ Test Reports
+
+ It can be useful to append the report target in order to
generate an html summary of the tests that were just run. The
following command will run both the MongooseTest and GooseTest
test cases and generate an html summary of the results:
@@ -159,6 +164,16 @@
See the documentation for the "ant report" target for more details
on the generated report.
+ Test Profiles
+
+ There are a number of profiles defined for running the test suite.
+ These test profiles define how the test should be run. If the test
+ profile is not specified then 'default.testprofile' is utilised.
+ This runs the system tests against the Java InVM broker. Additional
+ test profiles exists as follows:
+
+ cpp : Runs against the built cpp tree broker.
+
ant report
The report target will generate an html summary of the current
diff --git a/java/common/Composite.tpl b/java/common/Composite.tpl
index 46a45b0b91..283fa24641 100644
--- a/java/common/Composite.tpl
+++ b/java/common/Composite.tpl
@@ -1,28 +1,30 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.qpidity.transport.codec.Decoder;
-import org.apache.qpidity.transport.codec.Encodable;
-import org.apache.qpidity.transport.codec.Encoder;
-import org.apache.qpidity.transport.codec.Validator;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encodable;
+import org.apache.qpid.transport.codec.Encoder;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.Frame;
${
from genutil import *
cls = klass(type)["@name"]
+segments = type["segments"]
+
if type.name in ("control", "command"):
base = "Method"
size = 0
pack = 2
- if type["segments"]:
+ if segments:
payload = "true"
else:
payload = "false"
@@ -80,12 +82,16 @@ if pack > 0:
out(" private $(PACK_TYPES[pack]) packing_flags = 0;\n");
fields = get_fields(type)
-params = get_parameters(fields)
+params = get_parameters(type, fields)
options = get_options(fields)
for f in fields:
if not f.empty:
out(" private $(f.type) $(f.name);\n")
+
+if segments:
+ out(" private Header header;\n")
+ out(" private ByteBuffer body;\n")
}
${
@@ -99,7 +105,11 @@ for f in fields:
if f.option: continue
out(" $(f.set)($(f.name));\n")
-if options:
+if segments:
+ out(" setHeader(header);\n")
+ out(" setBody(body);\n")
+
+if options or base == "Method":
out("""
for (int i=0; i < _options.length; i++) {
switch (_options[i]) {
@@ -108,7 +118,11 @@ if options:
for f in options:
out(" case $(f.option): packing_flags |= $(f.flag_mask(pack)); break;\n")
- out(""" case NO_OPTION: break;
+ if base == "Method":
+ out(""" case SYNC: this.setSync(true); break;
+ case BATCH: this.setBatch(true); break;
+""")
+ out(""" case NONE: break;
default: throw new IllegalArgumentException("invalid option: " + _options[i]);
}
}
@@ -150,7 +164,6 @@ else:
}
public final $name $(f.set)($(f.type) value) {
- $(f.check)
${
if not f.empty:
out(" this.$(f.name) = value;")
@@ -169,6 +182,44 @@ if pack > 0:
""")
}
+${
+if segments:
+ out(""" public final Header getHeader() {
+ return this.header;
+ }
+
+ public final void setHeader(Header header) {
+ this.header = header;
+ }
+
+ public final $name header(Header header) {
+ setHeader(header);
+ return this;
+ }
+
+ public final ByteBuffer getBody() {
+ if (this.body == null)
+ {
+ return null;
+ }
+ else
+ {
+ return this.body.slice();
+ }
+ }
+
+ public final void setBody(ByteBuffer body) {
+ this.body = body;
+ }
+
+ public final $name body(ByteBuffer body)
+ {
+ setBody(body);
+ return this;
+ }
+""")
+}
+
public void write(Encoder enc)
{
${
diff --git a/java/common/Constant.tpl b/java/common/Constant.tpl
index 695812ea75..7194a61dfc 100644
--- a/java/common/Constant.tpl
+++ b/java/common/Constant.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
${from genutil import *}
diff --git a/java/common/Enum.tpl b/java/common/Enum.tpl
index 337feb7065..2ec1d22522 100644
--- a/java/common/Enum.tpl
+++ b/java/common/Enum.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
public enum $name {
${
diff --git a/java/common/Invoker.tpl b/java/common/Invoker.tpl
index d9905c71a0..9158922df7 100644
--- a/java/common/Invoker.tpl
+++ b/java/common/Invoker.tpl
@@ -1,5 +1,6 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
+import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -15,8 +16,8 @@ from genutil import *
for c in composites:
name = cname(c)
fields = get_fields(c)
- params = get_parameters(fields)
- args = get_arguments(fields)
+ params = get_parameters(c, fields)
+ args = get_arguments(c, fields)
result = c["result"]
if result:
if not result["@type"]:
@@ -32,9 +33,9 @@ for c in composites:
jclass = ""
out("""
- public $jresult $(dromedary(name))($(", ".join(params))) {
- $(jreturn)invoke(new $name($(", ".join(args)))$jclass);
- }
+ public final $jresult $(dromedary(name))($(", ".join(params))) {
+ $(jreturn)invoke(new $name($(", ".join(args)))$jclass);
+ }
""")
}
diff --git a/java/common/MethodDelegate.tpl b/java/common/MethodDelegate.tpl
index e5ab1ae1e7..84fa0e43da 100644
--- a/java/common/MethodDelegate.tpl
+++ b/java/common/MethodDelegate.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
public abstract class MethodDelegate<C> {
diff --git a/java/common/Option.tpl b/java/common/Option.tpl
index 5fa2b95b9f..d45c004f6f 100644
--- a/java/common/Option.tpl
+++ b/java/common/Option.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
public enum Option {
@@ -15,5 +15,6 @@ for c in composites:
if not options.has_key(option):
options[option] = None
out(" $option,\n")}
- NO_OPTION
+ BATCH,
+ NONE
}
diff --git a/java/common/StructFactory.tpl b/java/common/StructFactory.tpl
index b27621b1d2..f3dcbbd68a 100644
--- a/java/common/StructFactory.tpl
+++ b/java/common/StructFactory.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
class StructFactory {
diff --git a/java/common/Type.tpl b/java/common/Type.tpl
index c869934538..c58e08a342 100644
--- a/java/common/Type.tpl
+++ b/java/common/Type.tpl
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
${from genutil import *}
diff --git a/java/common/bin/qpid-run b/java/common/bin/qpid-run
index c9e37b21a1..1de0048f48 100755
--- a/java/common/bin/qpid-run
+++ b/java/common/bin/qpid-run
@@ -37,19 +37,39 @@ die() {
exit 1
}
+OFF=0
+WARN=1
+INFO=2
+
+if [ -z "$QPID_RUN_LOG" ]; then
+ QPID_RUN_LOG=$OFF
+fi
+
+log() {
+ if [ "$1" -le "$QPID_RUN_LOG" ]; then
+ shift
+ echo "$@"
+ fi
+}
+
if [ -z $AMQJ_LOGGING_LEVEL ]; then
export AMQJ_LOGGING_LEVEL=info
fi
if [ -z "$QPID_HOME" ]; then
- die "QPID_HOME must be set"
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
fi
if [ -z "$QPID_WORK" ]; then
- echo Setting QPID_WORK to $HOME as default
+ log $INFO Setting QPID_WORK to $HOME as default
QPID_WORK=$HOME
fi
+if [ -z "$JAVA" ]; then
+ JAVA=java
+fi
+
if $cygwin; then
QPID_HOME=$(cygpath -w $QPID_HOME)
QPID_WORK=$(cygpath -w $QPID_WORK)
@@ -64,10 +84,10 @@ SYSTEM_PROPS="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL -DQPID_HOME=$QPID_HOME -D
#Using X character to avoid probs with empty strings
if [ -n "$QPID_LOG_PREFIX" ]; then
if [ "X$QPID_LOG_PREFIX" = "XPID" ]; then
- echo Using pid in qpid log name prefix
+ log $INFO Using pid in qpid log name prefix
LOG_PREFIX=" -Dlogprefix=$$"
else
- echo Using qpid logprefix property
+ log $INFO Using qpid logprefix property
LOG_PREFIX=" -Dlogprefix=$QPID_LOG_PREFIX"
fi
SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_PREFIX}"
@@ -75,16 +95,16 @@ fi
if [ -n "$QPID_LOG_SUFFIX" ]; then
if [ "X$QPID_LOG_SUFFIX" = "XPID" ]; then
- echo Using pid in qpid log name suffix
+ log $INFO Using pid in qpid log name suffix
LOG_SUFFIX=" -Dlogsuffix=$$"
else
- echo Using qpig logsuffix property
+ log $INFO Using qpig logsuffix property
LOG_SUFFIX=" -Dlogsuffix=$QPID_LOG_SUFFIX"
fi
SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_SUFFIX}"
fi
-echo System Properties set to $SYSTEM_PROPS
+log $INFO System Properties set to $SYSTEM_PROPS
program=$(basename $0)
sourced=${BASH_SOURCE[0]}
@@ -109,26 +129,26 @@ unset CLASSPATH
#Use QPID_CLASSPATH if set
if [ -n "$QPID_CLASSPATH" ]; then
export CLASSPATH=$QPID_CLASSPATH
- echo "Using QPID_CLASSPATH" $QPID_CLASSPATH
+ log $INFO "Using QPID_CLASSPATH" $QPID_CLASSPATH
else
- echo "Warning: Qpid classpath not set. CLASSPATH must include qpid jars."
+ log $WARN "Warning: Qpid classpath not set. CLASSPATH must include qpid jars."
fi
#Use QPID_JAVA_GC if set
if [ -n "$QPID_JAVA_GC" ]; then
export JAVA_GC=$QPID_JAVA_GC
- echo "Using QPID_JAVA_GC setting" $QPID_JAVA_GC
+ log $INFO "Using QPID_JAVA_GC setting" $QPID_JAVA_GC
else
- echo "Info: QPID_JAVA_GC not set. Defaulting to JAVA_GC" $JAVA_GC
+ log $INFO "Info: QPID_JAVA_GC not set. Defaulting to JAVA_GC" $JAVA_GC
fi
#Use QPID_JAVA_MEM if set
if [ -n "$QPID_JAVA_MEM" ]; then
export JAVA_MEM=$QPID_JAVA_MEM
- echo "Using QPID_JAVA_MEM setting" $QPID_JAVA_MEM
+ log $INFO "Using QPID_JAVA_MEM setting" $QPID_JAVA_MEM
else
- echo "Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM" $JAVA_MEM
+ log $INFO "Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM" $JAVA_MEM
fi
declare -a RUN_ARGS JAVA_ARGS
@@ -172,7 +192,7 @@ for arg in "${RUN_ARGS[@]}"; do
;;
-run:jpda)
#USAGE: adds debugging options to the java command, use
-#USAGE: JDPA_TRANSPORT and JPDA_ADDRESS to customize the debugging
+#USAGE: JPDA_TRANSPORT and JPDA_ADDRESS to customize the debugging
#USAGE: behavior and use JPDA_OPTS to override it entirely
if [ -z "$JPDA_OPTS" ]; then
JPDA_OPTS="-Xdebug -Xrunjdwp:transport=${JPDA_TRANSPORT:-dt_socket},address=${JPDA_ADDRESS:-8000},server=y,suspend=n"
diff --git a/java/common/codegen b/java/common/codegen
index ab1ab1c542..6cd51565ea 100755
--- a/java/common/codegen
+++ b/java/common/codegen
@@ -7,7 +7,7 @@ from genutil import *
out_dir = sys.argv[1]
spec_file = sys.argv[2]
tpl_dir = sys.argv[3]
-pkg_dir = os.path.join(out_dir, "org/apache/qpidity/transport")
+pkg_dir = os.path.join(out_dir, "org/apache/qpid/transport")
if not os.path.exists(pkg_dir):
os.makedirs(pkg_dir)
diff --git a/java/common/genutil.py b/java/common/genutil.py
index 9636a91cc3..f8f234548c 100644
--- a/java/common/genutil.py
+++ b/java/common/genutil.py
@@ -170,18 +170,15 @@ class Field:
if self.type_node.name == "struct":
self.read = "(%s) dec.readStruct(%s.TYPE)" % (tname, tname)
self.write = "enc.writeStruct(%s.TYPE, check(struct).%s)" % (tname, self.name)
- self.check = ""
self.coder = "Struct"
elif self.type_node.name == "domain":
self.coder = camel(0, self.prim_type["@name"])
self.read = "%s.get(dec.read%s())" % (tname, self.coder)
self.write = "enc.write%s(check(struct).%s.getValue())" % (self.coder, self.name)
- self.check = ""
else:
self.coder = camel(0, self.type_node["@name"])
self.read = "dec.read%s()" % self.coder
self.write = "enc.write%s(check(struct).%s)" % (self.coder, self.name)
- self.check = "Validator.check%s(value);" % self.coder
self.type = jtype(self.type_node)
self.default = DEFAULTS.get(self.type, "null")
self.has = camel(1, "has", self.name)
@@ -206,7 +203,7 @@ def get_fields(nd):
index += 1
return fields
-def get_parameters(fields):
+def get_parameters(type, fields):
params = []
options = False
for f in fields:
@@ -214,11 +211,14 @@ def get_parameters(fields):
options = True
else:
params.append("%s %s" % (f.type, f.name))
- if options:
+ if type["segments"]:
+ params.append("Header header")
+ params.append("ByteBuffer body")
+ if options or type.name in ("control", "command"):
params.append("Option ... _options")
return params
-def get_arguments(fields):
+def get_arguments(type, fields):
args = []
options = False
for f in fields:
@@ -226,7 +226,10 @@ def get_arguments(fields):
options = True
else:
args.append(f.name)
- if options:
+ if type["segments"]:
+ args.append("header")
+ args.append("body")
+ if options or type.name in ("control", "command"):
args.append("_options")
return args
diff --git a/java/common/pom.xml b/java/common/pom.xml
index 714087d843..894ca26710 100644
--- a/java/common/pom.xml
+++ b/java/common/pom.xml
@@ -61,7 +61,7 @@
<!-- <exec executable="python">
<arg line="generate"/>
<arg line="${generated.path}"/>
- <arg line="org.apache.qpidity"/>
+ <arg line="org.apache.qpid"/>
<arg line="${specs.dir}/amqp-transitional.0-10.xml"/>
</exec> -->
</tasks>
diff --git a/java/common/src/main/java/log4j.properties b/java/common/src/main/java/log4j.properties
index 6d596d1d19..44f89dc805 100644
--- a/java/common/src/main/java/log4j.properties
+++ b/java/common/src/main/java/log4j.properties
@@ -19,9 +19,12 @@
log4j.rootLogger=${root.logging.level}
+log4j.logger.qpid.protocol=${amqj.protocol.logging.level}, console
+log4j.additivity.qpid.protocol=false
log4j.logger.org.apache.qpid=${amqj.logging.level}, console
log4j.additivity.org.apache.qpid=false
+
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=all
log4j.appender.console.layout=org.apache.log4j.PatternLayout
diff --git a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java
index bed80d5954..0c311b6645 100644
--- a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java
+++ b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java
@@ -62,7 +62,6 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator
private static final class FixedSizeByteBuffer extends ByteBuffer
{
private java.nio.ByteBuffer buf;
- private int refCount = 1;
private int mark = -1;
@@ -70,36 +69,14 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator
{
this.buf = buf;
buf.order( ByteOrder.BIG_ENDIAN );
- refCount = 1;
}
public synchronized void acquire()
{
- if( refCount <= 0 )
- {
- throw new IllegalStateException( "Already released buffer." );
- }
-
- refCount ++;
}
public void release()
{
- synchronized( this )
- {
- if( refCount <= 0 )
- {
- refCount = 0;
- throw new IllegalStateException(
- "Already released buffer. You released the buffer too many times." );
- }
-
- refCount --;
- if( refCount > 0)
- {
- return;
- }
- }
}
public java.nio.ByteBuffer buf()
@@ -157,50 +134,12 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator
{
if( newCapacity > capacity() )
{
- // Allocate a new buffer and transfer all settings to it.
- int pos = position();
- int limit = limit();
- ByteOrder bo = order();
-
- capacity0( newCapacity );
- buf.limit( limit );
- if( mark >= 0 )
- {
- buf.position( mark );
- buf.mark();
- }
- buf.position( pos );
- buf.order( bo );
+ throw new IllegalArgumentException();
}
return this;
}
- protected void capacity0( int requestedCapacity )
- {
- int newCapacity = MINIMUM_CAPACITY;
- while( newCapacity < requestedCapacity )
- {
- newCapacity <<= 1;
- }
-
- java.nio.ByteBuffer oldBuf = this.buf;
- java.nio.ByteBuffer newBuf;
- if( isDirect() )
- {
- newBuf = java.nio.ByteBuffer.allocateDirect( newCapacity );
- }
- else
- {
- newBuf = java.nio.ByteBuffer.allocate( newCapacity );
- }
-
- newBuf.clear();
- oldBuf.clear();
- newBuf.put( oldBuf );
- this.buf = newBuf;
- }
-
public boolean isAutoExpand()
diff --git a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
index c515263317..4fd28c4eb5 100644
--- a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
+++ b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java
@@ -31,7 +31,6 @@ import java.util.Iterator;
* A default implementation of {@link org.apache.mina.common.IoFuture}.
*
* @author The Apache Directory Project (mina-dev@directory.apache.org)
- * @version $Rev: 440259 $, $Date: 2006-09-05 14:01:47 +0900 (í™”, 05 9ì›” 2006) $
*/
public class DefaultIoFuture implements IoFuture
{
diff --git a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
index f6f596da95..ef9420ba87 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
@@ -54,6 +54,6 @@ public class AMQChannelException extends AMQException
public AMQFrame getCloseFrame(int channel)
{
MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
- return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId));
+ return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId));
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java b/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java
index 6cdd57d6f2..fa69f7f91b 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java
@@ -21,6 +21,10 @@
package org.apache.qpid;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
import org.apache.qpid.protocol.AMQConstant;
/**
@@ -35,6 +39,8 @@ import org.apache.qpid.protocol.AMQConstant;
*/
public class AMQConnectionFailureException extends AMQException
{
+ Collection<Exception> _exceptions;
+
public AMQConnectionFailureException(String message, Throwable cause)
{
super(null, message, cause);
@@ -44,4 +50,16 @@ public class AMQConnectionFailureException extends AMQException
{
super(errorCode, message, cause);
}
+
+ public AMQConnectionFailureException(String message, Collection<Exception> exceptions)
+ {
+ // Blah, I hate ? but java won't let super() be anything other than the first thing, sorry...
+ super (null, message, exceptions.isEmpty() ? null : exceptions.iterator().next());
+ this._exceptions = exceptions;
+ }
+
+ public Collection<Exception> getLinkedExceptions()
+ {
+ return _exceptions;
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpidity/BrokerDetails.java b/java/common/src/main/java/org/apache/qpid/BrokerDetails.java
index 29a4f5a9c0..63f67a7857 100644
--- a/java/common/src/main/java/org/apache/qpidity/BrokerDetails.java
+++ b/java/common/src/main/java/org/apache/qpid/BrokerDetails.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity;
+package org.apache.qpid;
import java.util.Map;
diff --git a/java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java b/java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java
index 6de6055f1c..201d43e21f 100644
--- a/java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java
+++ b/java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity;
+package org.apache.qpid;
import java.util.HashMap;
import java.util.Map;
diff --git a/java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java b/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java
index 4e05aa574c..f17782ebf4 100644
--- a/java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java
+++ b/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java
@@ -18,13 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity;
+package org.apache.qpid;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.Sender;
+import org.apache.qpid.transport.Sender;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
@@ -41,6 +41,11 @@ public class ConsoleOutput implements Sender<ByteBuffer>
System.out.println(str(buf));
}
+ public void flush()
+ {
+ // pass
+ }
+
public void close()
{
System.out.println("CLOSED");
diff --git a/java/common/src/main/java/org/apache/qpidity/ErrorCode.java b/java/common/src/main/java/org/apache/qpid/ErrorCode.java
index 4b18c46d16..be1ad16dd5 100644
--- a/java/common/src/main/java/org/apache/qpidity/ErrorCode.java
+++ b/java/common/src/main/java/org/apache/qpid/ErrorCode.java
@@ -1,4 +1,4 @@
-package org.apache.qpidity;
+package org.apache.qpid;
public enum ErrorCode
{
diff --git a/java/common/src/main/java/org/apache/qpidity/QpidConfig.java b/java/common/src/main/java/org/apache/qpid/QpidConfig.java
index b5aad12f10..e8d42fdf83 100644
--- a/java/common/src/main/java/org/apache/qpidity/QpidConfig.java
+++ b/java/common/src/main/java/org/apache/qpid/QpidConfig.java
@@ -1,4 +1,4 @@
-package org.apache.qpidity;
+package org.apache.qpid;
/**
* API to configure the Security parameters of the client.
@@ -11,11 +11,11 @@ public class QpidConfig
private static QpidConfig _instance = new QpidConfig();
private SecurityMechanism[] securityMechanisms =
- new SecurityMechanism[]{new SecurityMechanism("PLAIN","org.apache.qpidity.security.UsernamePasswordCallbackHandler"),
- new SecurityMechanism("CRAM_MD5","org.apache.qpidity.security.UsernamePasswordCallbackHandler")};
+ new SecurityMechanism[]{new SecurityMechanism("PLAIN","org.apache.qpid.security.UsernamePasswordCallbackHandler"),
+ new SecurityMechanism("CRAM_MD5","org.apache.qpid.security.UsernamePasswordCallbackHandler")};
private SaslClientFactory[] saslClientFactories =
- new SaslClientFactory[]{new SaslClientFactory("AMQPLAIN","org.apache.qpidity.security.amqplain.AmqPlainSaslClientFactory")};
+ new SaslClientFactory[]{new SaslClientFactory("AMQPLAIN","org.apache.qpid.security.amqplain.AmqPlainSaslClientFactory")};
private QpidConfig(){}
diff --git a/java/common/src/main/java/org/apache/qpidity/QpidException.java b/java/common/src/main/java/org/apache/qpid/QpidException.java
index 81e9145282..8503adaef8 100644
--- a/java/common/src/main/java/org/apache/qpidity/QpidException.java
+++ b/java/common/src/main/java/org/apache/qpid/QpidException.java
@@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity;
+package org.apache.qpid;
public class QpidException extends Exception
{
diff --git a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java b/java/common/src/main/java/org/apache/qpid/SecurityHelper.java
index a72997813a..dda5a6506d 100644
--- a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java
+++ b/java/common/src/main/java/org/apache/qpid/SecurityHelper.java
@@ -18,15 +18,15 @@
* under the License.
*
*/
-package org.apache.qpidity;
+package org.apache.qpid;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;
-import org.apache.qpidity.security.AMQPCallbackHandler;
-import org.apache.qpidity.security.CallbackHandlerRegistry;
+import org.apache.qpid.security.AMQPCallbackHandler;
+import org.apache.qpid.security.CallbackHandlerRegistry;
public class SecurityHelper
{
diff --git a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java b/java/common/src/main/java/org/apache/qpid/ToyBroker.java
index 5f9917e30a..83d434b20a 100644
--- a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java
+++ b/java/common/src/main/java/org/apache/qpid/ToyBroker.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpidity;
+package org.apache.qpid;
-import org.apache.qpidity.transport.*;
-import org.apache.qpidity.transport.network.mina.MinaHandler;
+import org.apache.qpid.transport.*;
+import org.apache.qpid.transport.network.mina.MinaHandler;
-import static org.apache.qpidity.transport.util.Functions.str;
+import static org.apache.qpid.transport.util.Functions.str;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -45,10 +45,6 @@ class ToyBroker extends SessionDelegate
{
private ToyExchange exchange;
- private MessageTransfer xfr = null;
- private DeliveryProperties props = null;
- private Header header = null;
- private List<Data> body = null;
private Map<String,Consumer> consumers = new ConcurrentHashMap<String,Consumer>();
public ToyBroker(ToyExchange exchange)
@@ -103,22 +99,10 @@ class ToyBroker extends SessionDelegate
@Override public void messageTransfer(Session ssn, MessageTransfer xfr)
{
- this.xfr = xfr;
- body = new ArrayList<Data>();
- System.out.println("received transfer " + xfr.getDestination());
- }
-
- @Override public void header(Session ssn, Header header)
- {
- if (xfr == null || body == null)
- {
- ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR,
- "no method segment");
- ssn.close();
- return;
- }
-
- props = header.get(DeliveryProperties.class);
+ String dest = xfr.getDestination();
+ System.out.println("received transfer " + dest);
+ Header header = xfr.getHeader();
+ DeliveryProperties props = header.get(DeliveryProperties.class);
if (props != null)
{
System.out.println("received headers routing_key " + props.getRoutingKey());
@@ -130,70 +114,31 @@ class ToyBroker extends SessionDelegate
System.out.println(mp.getApplicationHeaders());
}
- this.header = header;
- }
-
- @Override public void data(Session ssn, Data data)
- {
- if (xfr == null || body == null)
+ if (exchange.route(dest,props.getRoutingKey(),xfr))
{
- ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR, "no method segment");
- ssn.close();
- return;
+ System.out.println("queued " + xfr);
+ dispatchMessages(ssn);
}
-
- body.add(data);
-
- if (data.isLast())
+ else
{
- String dest = xfr.getDestination();
- Message m = new Message(header, body);
- if (exchange.route(dest,props.getRoutingKey(),m))
- {
- System.out.println("queued " + m);
- dispatchMessages(ssn);
- }
- else
+ if (props == null || !props.getDiscardUnroutable())
{
-
- reject(ssn);
+ RangeSet ranges = new RangeSet();
+ ranges.add(xfr.getId());
+ ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE,
+ "no such destination");
}
- ssn.processed(xfr);
- xfr = null;
- body = null;
- }
- }
-
- private void reject(Session ssn)
- {
- if (props != null && props.getDiscardUnroutable())
- {
- return;
- }
- else
- {
- RangeSet ranges = new RangeSet();
- ranges.add(xfr.getId());
- ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE,
- "no such destination");
}
+ ssn.processed(xfr);
}
- private void transferMessageToPeer(Session ssn,String dest, Message m)
+ private void transferMessageToPeer(Session ssn,String dest, MessageTransfer m)
{
System.out.println("\n==================> Transfering message to: " +dest + "\n");
- ssn.messageTransfer(dest, MessageAcceptMode.EXPLICIT,
- MessageAcquireMode.PRE_ACQUIRED);
- ssn.header(m.header);
- for (Data d : m.body)
- {
- for (ByteBuffer b : d.getFragments())
- {
- ssn.data(b);
- }
- }
- ssn.endData();
+ ssn.messageTransfer(m.getDestination(), MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ m.getHeader(), m.getBody());
}
private void dispatchMessages(Session ssn)
@@ -207,8 +152,8 @@ class ToyBroker extends SessionDelegate
private void checkAndSendMessagesToConsumer(Session ssn,String dest)
{
Consumer c = consumers.get(dest);
- LinkedBlockingQueue<Message> queue = exchange.getQueue(c._queueName);
- Message m = queue.poll();
+ LinkedBlockingQueue<MessageTransfer> queue = exchange.getQueue(c._queueName);
+ MessageTransfer m = queue.poll();
while (m != null && c._credit>0)
{
transferMessageToPeer(ssn,dest,m);
@@ -217,46 +162,6 @@ class ToyBroker extends SessionDelegate
}
}
- class Message
- {
- private final Header header;
- private final List<Data> body;
-
- public Message(Header header, List<Data> body)
- {
- this.header = header;
- this.body = body;
- }
-
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
-
- if (header != null)
- {
- boolean first = true;
- for (Struct st : header.getStructs())
- {
- if (first) { first = false; }
- else { sb.append(" "); }
- sb.append(st);
- }
- }
-
- for (Data d : body)
- {
- for (ByteBuffer b : d.getFragments())
- {
- sb.append(" | ");
- sb.append(str(b));
- }
- }
-
- return sb.toString();
- }
-
- }
-
// ugly, but who cares :)
// assumes unit is always no of messages, not bytes
// assumes it's credit mode and not window
diff --git a/java/common/src/main/java/org/apache/qpidity/ToyClient.java b/java/common/src/main/java/org/apache/qpid/ToyClient.java
index a3233afcbe..cb10859c9f 100644
--- a/java/common/src/main/java/org/apache/qpidity/ToyClient.java
+++ b/java/common/src/main/java/org/apache/qpid/ToyClient.java
@@ -18,12 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity;
+package org.apache.qpid;
+import java.nio.*;
import java.util.*;
-import org.apache.qpidity.transport.*;
-import org.apache.qpidity.transport.network.mina.MinaHandler;
+import org.apache.qpid.transport.*;
+import org.apache.qpid.transport.network.mina.MinaHandler;
/**
@@ -47,17 +48,9 @@ class ToyClient extends SessionDelegate
}
}
- @Override public void header(Session ssn, Header header)
+ @Override public void messageTransfer(Session ssn, MessageTransfer xfr)
{
- for (Struct st : header.getStructs())
- {
- System.out.println("header: " + st);
- }
- }
-
- @Override public void data(Session ssn, Data data)
- {
- System.out.println("got data: " + data);
+ System.out.println("msg: " + xfr);
}
public static final void main(String[] args)
@@ -75,9 +68,8 @@ class ToyClient extends SessionDelegate
}
public void closed() {}
});
- conn.send(new ConnectionEvent(0, new ProtocolHeader(1,
- TransportConstants.getVersionMajor(),
- TransportConstants.getVersionMinor())));
+ conn.send(new ProtocolHeader
+ (1, 0, 10));
Channel ch = conn.getChannel(0);
Session ssn = new Session("my-session".getBytes());
@@ -112,16 +104,16 @@ class ToyClient extends SessionDelegate
map.put("binary", new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
ssn.messageTransfer("asdf", MessageAcceptMode.EXPLICIT,
- MessageAcquireMode.PRE_ACQUIRED);
- ssn.header(new DeliveryProperties(),
- new MessageProperties().setApplicationHeaders(map));
- ssn.data("this is the data");
- ssn.endData();
+ MessageAcquireMode.PRE_ACQUIRED,
+ new Header(new DeliveryProperties(),
+ new MessageProperties()
+ .setApplicationHeaders(map)),
+ "this is the data");
ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT,
- MessageAcquireMode.PRE_ACQUIRED);
- ssn.data("this should be rejected");
- ssn.endData();
+ MessageAcquireMode.PRE_ACQUIRED,
+ null,
+ "this should be rejected");
ssn.sync();
Future<QueueQueryResult> future = ssn.queueQuery("asdf");
diff --git a/java/common/src/main/java/org/apache/qpidity/ToyExchange.java b/java/common/src/main/java/org/apache/qpid/ToyExchange.java
index eab5f6c078..c638679596 100644
--- a/java/common/src/main/java/org/apache/qpidity/ToyExchange.java
+++ b/java/common/src/main/java/org/apache/qpid/ToyExchange.java
@@ -1,4 +1,4 @@
-package org.apache.qpidity;
+package org.apache.qpid;
import java.util.ArrayList;
import java.util.HashMap;
@@ -9,42 +9,43 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.qpidity.ToyBroker.Message;
+import org.apache.qpid.transport.MessageTransfer;
+
public class ToyExchange
{
final static String DIRECT = "amq.direct";
final static String TOPIC = "amq.topic";
- private Map<String,List<LinkedBlockingQueue<Message>>> directEx = new HashMap<String,List<LinkedBlockingQueue<Message>>>();
- private Map<String,List<LinkedBlockingQueue<Message>>> topicEx = new HashMap<String,List<LinkedBlockingQueue<Message>>>();
- private Map<String,LinkedBlockingQueue<Message>> queues = new HashMap<String,LinkedBlockingQueue<Message>>();
+ private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> directEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>();
+ private Map<String,List<LinkedBlockingQueue<MessageTransfer>>> topicEx = new HashMap<String,List<LinkedBlockingQueue<MessageTransfer>>>();
+ private Map<String,LinkedBlockingQueue<MessageTransfer>> queues = new HashMap<String,LinkedBlockingQueue<MessageTransfer>>();
public void createQueue(String name)
{
- queues.put(name, new LinkedBlockingQueue<Message>());
+ queues.put(name, new LinkedBlockingQueue<MessageTransfer>());
}
- public LinkedBlockingQueue<Message> getQueue(String name)
+ public LinkedBlockingQueue<MessageTransfer> getQueue(String name)
{
return queues.get(name);
}
public void bindQueue(String type,String binding,String queueName)
{
- LinkedBlockingQueue<Message> queue = queues.get(queueName);
+ LinkedBlockingQueue<MessageTransfer> queue = queues.get(queueName);
binding = normalizeKey(binding);
if(DIRECT.equals(type))
{
if (directEx.containsKey(binding))
{
- List<LinkedBlockingQueue<Message>> list = directEx.get(binding);
+ List<LinkedBlockingQueue<MessageTransfer>> list = directEx.get(binding);
list.add(queue);
}
else
{
- List<LinkedBlockingQueue<Message>> list = new LinkedList<LinkedBlockingQueue<Message>>();
+ List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>();
list.add(queue);
directEx.put(binding,list);
}
@@ -53,21 +54,21 @@ public class ToyExchange
{
if (topicEx.containsKey(binding))
{
- List<LinkedBlockingQueue<Message>> list = topicEx.get(binding);
+ List<LinkedBlockingQueue<MessageTransfer>> list = topicEx.get(binding);
list.add(queue);
}
else
{
- List<LinkedBlockingQueue<Message>> list = new LinkedList<LinkedBlockingQueue<Message>>();
+ List<LinkedBlockingQueue<MessageTransfer>> list = new LinkedList<LinkedBlockingQueue<MessageTransfer>>();
list.add(queue);
topicEx.put(binding,list);
}
}
}
- public boolean route(String dest,String routingKey,Message msg)
+ public boolean route(String dest, String routingKey, MessageTransfer msg)
{
- List<LinkedBlockingQueue<Message>> queues;
+ List<LinkedBlockingQueue<MessageTransfer>> queues;
if(DIRECT.equals(dest))
{
queues = directEx.get(routingKey);
@@ -101,9 +102,9 @@ public class ToyExchange
}
}
- private List<LinkedBlockingQueue<Message>> matchWildCard(String routingKey)
+ private List<LinkedBlockingQueue<MessageTransfer>> matchWildCard(String routingKey)
{
- List<LinkedBlockingQueue<Message>> selected = new ArrayList<LinkedBlockingQueue<Message>>();
+ List<LinkedBlockingQueue<MessageTransfer>> selected = new ArrayList<LinkedBlockingQueue<MessageTransfer>>();
for(String key: topicEx.keySet())
{
@@ -111,7 +112,7 @@ public class ToyExchange
Matcher m = p.matcher(routingKey);
if (m.find())
{
- for(LinkedBlockingQueue<Message> queue : topicEx.get(key))
+ for(LinkedBlockingQueue<MessageTransfer> queue : topicEx.get(key))
{
selected.add(queue);
}
@@ -121,9 +122,9 @@ public class ToyExchange
return selected;
}
- private void storeMessage(Message msg,List<LinkedBlockingQueue<Message>> selected)
+ private void storeMessage(MessageTransfer msg,List<LinkedBlockingQueue<MessageTransfer>> selected)
{
- for(LinkedBlockingQueue<Message> queue : selected)
+ for(LinkedBlockingQueue<MessageTransfer> queue : selected)
{
queue.offer(msg);
}
diff --git a/java/common/src/main/java/org/apache/qpidity/api/Message.java b/java/common/src/main/java/org/apache/qpid/api/Message.java
index f5488fde52..df6f279026 100644
--- a/java/common/src/main/java/org/apache/qpidity/api/Message.java
+++ b/java/common/src/main/java/org/apache/qpid/api/Message.java
@@ -1,11 +1,11 @@
-package org.apache.qpidity.api;
+package org.apache.qpid.api;
import java.io.IOException;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.MessageProperties;
-import org.apache.qpidity.transport.DeliveryProperties;
-import org.apache.qpidity.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
/*
* Licensed to the Apache Software Foundation (ASF) under one
diff --git a/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java
index 67f16e6a87..7371c12519 100644
--- a/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.common;
+import org.apache.qpid.framing.AMQShortString;
+
/**
* Specifies the available client property types that different clients can use to identify themselves with.
*
@@ -30,8 +32,21 @@ package org.apache.qpid.common;
*/
public enum ClientProperties
{
- instance,
- product,
- version,
- platform
+ instance("instance"),
+ product("product"),
+ version("version"),
+ platform("platform");
+
+ private final AMQShortString _amqShortString;
+
+ private ClientProperties(String name)
+ {
+ _amqShortString = new AMQShortString(name);
+ }
+
+
+ public AMQShortString toAMQShortString()
+ {
+ return _amqShortString;
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java b/java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java
index 89d7e7917f..49effc2dae 100644
--- a/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java
+++ b/java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java
@@ -15,11 +15,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpidity.dtx;
+package org.apache.qpid.dtx;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.QpidException;
import javax.transaction.xa.Xid;
@@ -241,9 +241,9 @@ public class XidImpl implements Xid
* @return The String representation of this Xid
* @throws QpidException In case of problem when converting this Xid into a string.
*/
- public static org.apache.qpidity.transport.Xid convert(Xid xid) throws QpidException
+ public static org.apache.qpid.transport.Xid convert(Xid xid) throws QpidException
{
- return new org.apache.qpidity.transport.Xid(xid.getFormatId(),
+ return new org.apache.qpid.transport.Xid(xid.getFormatId(),
xid.getGlobalTransactionId(),
xid.getBranchQualifier());
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
index 903b5bfa7a..a2fc3a03ef 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
@@ -50,4 +50,14 @@ public abstract class AMQDataBlock implements EncodableAMQDataBlock
return buffer;
}
+ public java.nio.ByteBuffer toNioByteBuffer()
+ {
+ final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate((int) getSize());
+
+ ByteBuffer buf = ByteBuffer.wrap(buffer);
+ writePayload(buf);
+ buffer.flip();
+ return buffer;
+ }
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
index a747aaeda7..a8e7f47db0 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
@@ -111,6 +111,8 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
private final byte[] _data;
private final int _offset;
private int _hashCode;
+ private String _asString = null;
+
private final int _length;
private static final char[] EMPTY_CHAR_ARRAY = new char[0];
@@ -137,7 +139,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
public AMQShortString(String data)
{
this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray());
-
+ _asString = data;
}
public AMQShortString(char[] data)
@@ -224,7 +226,6 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
}
}
-
/**
* Get the length of the short string
* @return length of the underlying byte array
@@ -419,9 +420,14 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
return chars;
}
+
public String asString()
{
- return new String(asChars());
+ if (_asString == null)
+ {
+ _asString = new String(asChars());
+ }
+ return _asString;
}
public boolean equals(Object o)
@@ -464,13 +470,49 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
return false;
}
- if ((_hashCode != 0) && (otherString._hashCode != 0) && (_hashCode != otherString._hashCode))
+ final int hashCode = _hashCode;
+
+ final int otherHashCode = otherString._hashCode;
+
+ if ((hashCode != 0) && (otherHashCode != 0) && (hashCode != otherHashCode))
+ {
+ return false;
+ }
+
+ final int length = _length;
+
+ if(length != otherString._length)
{
return false;
}
- return (_offset == 0 && otherString._offset == 0 && _length == _data.length && otherString._length == otherString._data.length && Arrays.equals(_data,otherString._data))
- || Arrays.equals(getBytes(),otherString.getBytes());
+
+ final byte[] data = _data;
+
+ final byte[] otherData = otherString._data;
+
+ final int offset = _offset;
+
+ final int otherOffset = otherString._offset;
+
+ if(offset == 0 && otherOffset == 0 && length == data.length && length == otherData.length)
+ {
+ return Arrays.equals(data, otherData);
+ }
+ else
+ {
+ int thisIdx = offset;
+ int otherIdx = otherOffset;
+ for(int i = length; i-- != 0; )
+ {
+ if(!(data[thisIdx++] == otherData[otherIdx++]))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
@@ -718,4 +760,17 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt
return false; //To change body of created methods use File | Settings | File Templates.
}
+
+ public static void main(String args[])
+ {
+ AMQShortString s = new AMQShortString("a.b.c.d.e.f.g.h.i.j.k");
+ AMQShortString s2 = s.substring(2, 7);
+
+ AMQShortStringTokenizer t = s2.tokenize((byte) '.');
+ while(t.hasMoreTokens())
+ {
+ System.err.println(t.nextToken());
+ }
+ }
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
index d6359baa0f..1ff39ca790 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
@@ -93,4 +93,24 @@ public class AMQTypedValue
{
return "[" + getType() + ": " + getValue() + "]";
}
+
+
+ public boolean equals(Object o)
+ {
+ if(o instanceof AMQTypedValue)
+ {
+ AMQTypedValue other = (AMQTypedValue) o;
+ return _type == other._type && (_value == null ? other._value == null : _value.equals(other._value));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ return _type.hashCode() ^ (_value == null ? 0 : _value.hashCode());
+ }
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index 9ba9b53b13..ed01c91804 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -74,7 +74,7 @@ public class FieldTable
buffer.skip((int) length);
}
- private AMQTypedValue getProperty(AMQShortString string)
+ public AMQTypedValue getProperty(AMQShortString string)
{
checkPropertyName(string);
@@ -891,6 +891,20 @@ public class FieldTable
return keys;
}
+ public Iterator<Map.Entry<AMQShortString, AMQTypedValue>> iterator()
+ {
+ if(_encodedForm != null)
+ {
+ return new FieldTableIterator(_encodedForm.duplicate().rewind(),(int)_encodedSize);
+ }
+ else
+ {
+ initMapIfNecessary();
+ return _properties.entrySet().iterator();
+ }
+ }
+
+
public Object get(AMQShortString key)
{
@@ -1050,6 +1064,95 @@ public class FieldTable
}
}
+ private static final class FieldTableEntry implements Map.Entry<AMQShortString, AMQTypedValue>
+ {
+ private final AMQTypedValue _value;
+ private final AMQShortString _key;
+
+ public FieldTableEntry(final AMQShortString key, final AMQTypedValue value)
+ {
+ _key = key;
+ _value = value;
+ }
+
+ public AMQShortString getKey()
+ {
+ return _key;
+ }
+
+ public AMQTypedValue getValue()
+ {
+ return _value;
+ }
+
+ public AMQTypedValue setValue(final AMQTypedValue value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object o)
+ {
+ if(o instanceof FieldTableEntry)
+ {
+ FieldTableEntry other = (FieldTableEntry) o;
+ return (_key == null ? other._key == null : _key.equals(other._key))
+ && (_value == null ? other._value == null : _value.equals(other._value));
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public int hashCode()
+ {
+ return (getKey()==null ? 0 : getKey().hashCode())
+ ^ (getValue()==null ? 0 : getValue().hashCode());
+ }
+
+ }
+
+
+ private static final class FieldTableIterator implements Iterator<Map.Entry<AMQShortString, AMQTypedValue>>
+ {
+
+ private final ByteBuffer _buffer;
+ private int _expectedRemaining;
+
+ public FieldTableIterator(ByteBuffer buffer, int length)
+ {
+ _buffer = buffer;
+ _expectedRemaining = buffer.remaining() - length;
+ }
+
+ public boolean hasNext()
+ {
+ return (_buffer.remaining() > _expectedRemaining);
+ }
+
+ public Map.Entry<AMQShortString, AMQTypedValue> next()
+ {
+ if(hasNext())
+ {
+ final AMQShortString key = EncodingUtils.readAMQShortString(_buffer);
+ AMQTypedValue value = AMQTypedValue.readFromBuffer(_buffer);
+ return new FieldTableEntry(key, value);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
+
+
public int hashCode()
{
initMapIfNecessary();
diff --git a/java/common/src/main/java/org/apache/qpid/pool/Job.java b/java/common/src/main/java/org/apache/qpid/pool/Job.java
index b2a09ac592..00da005515 100644
--- a/java/common/src/main/java/org/apache/qpid/pool/Job.java
+++ b/java/common/src/main/java/org/apache/qpid/pool/Job.java
@@ -50,7 +50,7 @@ import org.apache.mina.common.IoSession;
*
* @todo For better re-usability could make the completion handler optional. Only run it when one is set.
*/
-public class Job implements Runnable
+public class Job implements ReadWriteRunnable
{
/** The maximum number of events to process per run of the job. More events than this may be queued in the job. */
private final int _maxEvents;
@@ -67,18 +67,22 @@ public class Job implements Runnable
/** Holds the completion continuation, called upon completion of a run of the job. */
private final JobCompletionHandler _completionHandler;
+ private final boolean _readJob;
+
/**
* Creates a new job that aggregates many continuations together.
*
* @param session The Mina session.
* @param completionHandler The per job run, terminal continuation.
* @param maxEvents The maximum number of aggregated continuations to process per run of the job.
+ * @param readJob
*/
- Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents)
+ Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents, final boolean readJob)
{
_session = session;
_completionHandler = completionHandler;
_maxEvents = maxEvents;
+ _readJob = readJob;
}
/**
@@ -157,6 +161,22 @@ public class Job implements Runnable
}
}
+ public boolean isReadJob()
+ {
+ return _readJob;
+ }
+
+ public boolean isRead()
+ {
+ return _readJob;
+ }
+
+ public boolean isWrite()
+ {
+ return !_readJob;
+ }
+
+
/**
* Another interface for a continuation.
*
diff --git a/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
index 2912e54662..a080cc7e04 100644
--- a/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
+++ b/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
@@ -60,24 +60,6 @@ import java.util.concurrent.ExecutorService;
* <td> {@link Job}, {@link Job.JobCompletionHandler}
* </table>
*
- * @todo This seems a bit bizarre. ReadWriteThreadModel creates seperate pooling filters for read and write events.
- * The pooling filters themselves batch read and write events into jobs, but hand these jobs to a common thread
- * pool for execution. So the same thread pool ends up handling read and write events, albeit with many threads
- * so there is concurrency. But why go to the trouble of seperating out the read and write events in that case?
- * Why not just batch them into jobs together? Perhaps its so that seperate thread pools could be used for these
- * stages.
- *
- * @todo Why set an event limit of 10 on the Job? This also seems bizarre, as the job can have more than 10 events in
- * it. Its just that it runs them 10 at a time, but the completion hander here checks if there are more to run
- * and trips off another batch of 10 until they are all done. Why not just have a straight forward
- * consumer/producer queue scenario without the batches of 10? So instead of having many jobs with batches of 10
- * in them, just have one queue of events and worker threads taking the next event. There will be coordination
- * between worker threads and new events arriving on the job anyway, so the simpler scenario may have the same
- * amount of contention. I can see that the batches of 10 is done, so that no job is allowed to hog the worker
- * pool for too long. I'm not convinced this fairly complex scheme will actually add anything, and it might be
- * better to encapsulate it under a Queue interface anyway, so that different queue implementations can easily
- * be substituted in.
- *
* @todo The static helper methods are pointless. Could just call new.
*/
public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionHandler
@@ -96,17 +78,20 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo
private final int _maxEvents;
+ private final boolean _readFilter;
+
/**
* Creates a named pooling filter, on the specified shared thread pool.
*
* @param refCountingPool The thread pool reference.
* @param name The identifying name of the filter type.
*/
- public PoolingFilter(ReferenceCountingExecutorService refCountingPool, String name, int maxEvents)
+ public PoolingFilter(ReferenceCountingExecutorService refCountingPool, String name, int maxEvents, boolean readFilter)
{
_poolReference = refCountingPool;
_name = name;
_maxEvents = maxEvents;
+ _readFilter = readFilter;
}
/**
@@ -167,7 +152,6 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo
void fireAsynchEvent(Job job, Event event)
{
- // job.acquire(); //prevents this job being removed from _jobs
job.add(event);
final ExecutorService pool = _poolReference.getPool();
@@ -201,7 +185,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo
*/
public void createNewJobForSession(IoSession session)
{
- Job job = new Job(session, this, MAX_JOB_EVENTS);
+ Job job = new Job(session, this, MAX_JOB_EVENTS,_readFilter);
session.setAttribute(_name, job);
}
@@ -433,7 +417,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo
*/
public AsynchReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_read_events", MAX_JOB_EVENTS));
+ super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_read_events", MAX_JOB_EVENTS),true);
}
/**
@@ -476,7 +460,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo
*/
public AsynchWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_write_events", MAX_JOB_EVENTS));
+ super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_write_events", MAX_JOB_EVENTS),false);
}
/**
diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java
new file mode 100644
index 0000000000..8de0f93ce9
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java
@@ -0,0 +1,432 @@
+package org.apache.qpid.pool;
+
+import java.util.AbstractQueue;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public class ReadWriteJobQueue extends AbstractQueue<Runnable> implements BlockingQueue<Runnable>
+{
+
+ private final AtomicInteger _count = new AtomicInteger(0);
+
+ private final ReentrantLock _takeLock = new ReentrantLock();
+
+ private final Condition _notEmpty = _takeLock.newCondition();
+
+ private final ReentrantLock _putLock = new ReentrantLock();
+
+ private final ConcurrentLinkedQueue<ReadWriteRunnable> _readJobQueue = new ConcurrentLinkedQueue<ReadWriteRunnable>();
+
+ private final ConcurrentLinkedQueue<ReadWriteRunnable> _writeJobQueue = new ConcurrentLinkedQueue<ReadWriteRunnable>();
+
+
+ private class ReadWriteJobIterator implements Iterator<Runnable>
+ {
+
+ private boolean _onReads;
+ private Iterator<ReadWriteRunnable> _iter = _writeJobQueue.iterator();
+
+ public boolean hasNext()
+ {
+ if(!_iter.hasNext())
+ {
+ if(_onReads)
+ {
+ _iter = _readJobQueue.iterator();
+ _onReads = true;
+ return _iter.hasNext();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ public Runnable next()
+ {
+ if(_iter.hasNext())
+ {
+ return _iter.next();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public void remove()
+ {
+ _takeLock.lock();
+ try
+ {
+ _iter.remove();
+ _count.decrementAndGet();
+ }
+ finally
+ {
+ _takeLock.unlock();
+ }
+ }
+ }
+
+ public Iterator<Runnable> iterator()
+ {
+ return new ReadWriteJobIterator();
+ }
+
+ public int size()
+ {
+ return _count.get();
+ }
+
+ public boolean offer(final Runnable runnable)
+ {
+ final ReadWriteRunnable job = (ReadWriteRunnable) runnable;
+ final ReentrantLock putLock = _putLock;
+ putLock.lock();
+ try
+ {
+ if(job.isRead())
+ {
+ _readJobQueue.offer(job);
+ }
+ else
+ {
+ _writeJobQueue.offer(job);
+ }
+ if(_count.getAndIncrement() == 0)
+ {
+ _takeLock.lock();
+ try
+ {
+ _notEmpty.signal();
+ }
+ finally
+ {
+ _takeLock.unlock();
+ }
+ }
+ return true;
+ }
+ finally
+ {
+ putLock.unlock();
+ }
+ }
+
+ public void put(final Runnable runnable) throws InterruptedException
+ {
+ final ReadWriteRunnable job = (ReadWriteRunnable) runnable;
+ final ReentrantLock putLock = _putLock;
+ putLock.lock();
+
+ try
+ {
+ if(job.isRead())
+ {
+ _readJobQueue.offer(job);
+ }
+ else
+ {
+ _writeJobQueue.offer(job);
+ }
+ if(_count.getAndIncrement() == 0)
+ {
+ _takeLock.lock();
+ try
+ {
+ _notEmpty.signal();
+ }
+ finally
+ {
+ _takeLock.unlock();
+ }
+ }
+
+ }
+ finally
+ {
+ putLock.unlock();
+ }
+ }
+
+
+
+ public boolean offer(final Runnable runnable, final long timeout, final TimeUnit unit) throws InterruptedException
+ {
+ final ReadWriteRunnable job = (ReadWriteRunnable) runnable;
+ final ReentrantLock putLock = _putLock;
+ putLock.lock();
+
+ try
+ {
+ if(job.isRead())
+ {
+ _readJobQueue.offer(job);
+ }
+ else
+ {
+ _writeJobQueue.offer(job);
+ }
+ if(_count.getAndIncrement() == 0)
+ {
+ _takeLock.lock();
+ try
+ {
+ _notEmpty.signal();
+ }
+ finally
+ {
+ _takeLock.unlock();
+ }
+ }
+
+ return true;
+ }
+ finally
+ {
+ putLock.unlock();
+ }
+
+ }
+
+ public Runnable take() throws InterruptedException
+ {
+ final ReentrantLock takeLock = _takeLock;
+ takeLock.lockInterruptibly();
+ try
+ {
+ try
+ {
+ while (_count.get() == 0)
+ {
+ _notEmpty.await();
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ _notEmpty.signal();
+ throw ie;
+ }
+
+ ReadWriteRunnable job = _writeJobQueue.poll();
+ if(job == null)
+ {
+ job = _readJobQueue.poll();
+ }
+ int c = _count.getAndDecrement();
+ if (c > 1)
+ {
+ _notEmpty.signal();
+ }
+ return job;
+ }
+ finally
+ {
+ takeLock.unlock();
+ }
+
+
+ }
+
+ public Runnable poll(final long timeout, final TimeUnit unit) throws InterruptedException
+ {
+ final ReentrantLock takeLock = _takeLock;
+ final AtomicInteger count = _count;
+ long nanos = unit.toNanos(timeout);
+ takeLock.lockInterruptibly();
+ ReadWriteRunnable job = null;
+ try
+ {
+
+ for (;;)
+ {
+ if (count.get() > 0)
+ {
+ job = _writeJobQueue.poll();
+ if(job == null)
+ {
+ job = _readJobQueue.poll();
+ }
+ int c = count.getAndDecrement();
+ if (c > 1)
+ {
+ _notEmpty.signal();
+ }
+ break;
+ }
+ if (nanos <= 0)
+ {
+ return null;
+ }
+ try
+ {
+ nanos = _notEmpty.awaitNanos(nanos);
+ }
+ catch (InterruptedException ie)
+ {
+ _notEmpty.signal();
+ throw ie;
+ }
+ }
+ }
+ finally
+ {
+ takeLock.unlock();
+ }
+
+ return job;
+ }
+
+ public int remainingCapacity()
+ {
+ return Integer.MAX_VALUE;
+ }
+
+ public int drainTo(final Collection<? super Runnable> c)
+ {
+ int total = 0;
+
+ _putLock.lock();
+ _takeLock.lock();
+ try
+ {
+ ReadWriteRunnable job;
+ while((job = _writeJobQueue.peek())!= null)
+ {
+ c.add(job);
+ _writeJobQueue.poll();
+ _count.decrementAndGet();
+ total++;
+ }
+
+ while((job = _readJobQueue.peek())!= null)
+ {
+ c.add(job);
+ _readJobQueue.poll();
+ _count.decrementAndGet();
+ total++;
+ }
+
+ }
+ finally
+ {
+ _takeLock.unlock();
+ _putLock.unlock();
+ }
+ return total;
+ }
+
+ public int drainTo(final Collection<? super Runnable> c, final int maxElements)
+ {
+ int total = 0;
+
+ _putLock.lock();
+ _takeLock.lock();
+ try
+ {
+ ReadWriteRunnable job;
+ while(total<=maxElements && (job = _writeJobQueue.peek())!= null)
+ {
+ c.add(job);
+ _writeJobQueue.poll();
+ _count.decrementAndGet();
+ total++;
+ }
+
+ while(total<=maxElements && (job = _readJobQueue.peek())!= null)
+ {
+ c.add(job);
+ _readJobQueue.poll();
+ _count.decrementAndGet();
+ total++;
+ }
+
+ }
+ finally
+ {
+ _takeLock.unlock();
+ _putLock.unlock();
+ }
+ return total;
+
+ }
+
+ public Runnable poll()
+ {
+ final ReentrantLock takeLock = _takeLock;
+ takeLock.lock();
+ try
+ {
+ if(_count.get() > 0)
+ {
+ ReadWriteRunnable job = _writeJobQueue.poll();
+ if(job == null)
+ {
+ job = _readJobQueue.poll();
+ }
+ _count.decrementAndGet();
+ return job;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ finally
+ {
+ takeLock.unlock();
+ }
+
+ }
+
+ public Runnable peek()
+ {
+ final ReentrantLock takeLock = _takeLock;
+ takeLock.lock();
+ try
+ {
+ ReadWriteRunnable job = _writeJobQueue.peek();
+ if(job == null)
+ {
+ job = _readJobQueue.peek();
+ }
+ return job;
+ }
+ finally
+ {
+ takeLock.unlock();
+ }
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java
new file mode 100644
index 0000000000..ad04a923e1
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java
@@ -0,0 +1,27 @@
+package org.apache.qpid.pool;
+
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+public interface ReadWriteRunnable extends Runnable
+{
+ boolean isRead();
+ boolean isWrite();
+}
diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java b/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java
index 84c9e1f465..ce9c6ae4cb 100644
--- a/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java
+++ b/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java
@@ -22,6 +22,9 @@ package org.apache.qpid.pool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.LinkedBlockingQueue;
/**
* ReferenceCountingExecutorService wraps an ExecutorService in order to provide shared reference to it. It counts
@@ -84,6 +87,8 @@ public class ReferenceCountingExecutorService
/** Holds the number of executor threads to create. */
private int _poolSize = Integer.getInteger("amqj.read_write_pool_size", DEFAULT_POOL_SIZE);
+ private final boolean _useBiasedPool = Boolean.getBoolean("org.apache.qpid.use_write_biased_pool");
+
/**
* Retrieves the singleton instance of this reference counter.
*
@@ -105,15 +110,28 @@ public class ReferenceCountingExecutorService
*
* @return An executor service.
*/
- ExecutorService acquireExecutorService()
+ public ExecutorService acquireExecutorService()
{
synchronized (_lock)
{
if (_refCount++ == 0)
{
- _pool = Executors.newFixedThreadPool(_poolSize);
+// _pool = Executors.newFixedThreadPool(_poolSize);
+
+ // Use a job queue that biases to writes
+ if(_useBiasedPool)
+ {
+ _pool = new ThreadPoolExecutor(_poolSize, _poolSize,
+ 0L, TimeUnit.MILLISECONDS,
+ new ReadWriteJobQueue());
+ }
+ else
+ {
+ _pool = Executors.newFixedThreadPool(_poolSize);
+ }
}
+
return _pool;
}
}
@@ -122,7 +140,7 @@ public class ReferenceCountingExecutorService
* Releases a reference to a shared executor service, decrementing the reference count. If the refence count falls
* to zero, the executor service is shut down.
*/
- void releaseExecutorService()
+ public void releaseExecutorService()
{
synchronized (_lock)
{
diff --git a/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java b/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
index 59003225b7..b58e7d01dc 100644
--- a/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
+++ b/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
@@ -21,8 +21,12 @@
package org.apache.qpid.protocol;
import org.apache.qpid.framing.*;
+import org.apache.qpid.transport.Sender;
import org.apache.qpid.AMQException;
+import java.nio.ByteBuffer;
+
+
/**
* AMQVersionAwareProtocolSession is implemented by all AMQP session classes, that need to provide an awareness to
* callers of the version of the AMQP protocol that they are able to work with.
@@ -54,4 +58,7 @@ public interface AMQVersionAwareProtocolSession extends AMQProtocolWriter, Proto
public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException;
+ public void setSender(Sender<ByteBuffer> sender);
+ public void init();
+
}
diff --git a/java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java
index 2e7afa1b87..a3dad9acdc 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java
+++ b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security;
+package org.apache.qpid.security;
import javax.security.auth.callback.CallbackHandler;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java b/java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java
index b23fea7e4a..8c80a1b5b7 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java
+++ b/java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpidity.security;
+package org.apache.qpid.security;
import java.util.HashMap;
import java.util.Map;
-import org.apache.qpidity.QpidConfig;
+import org.apache.qpid.QpidConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java b/java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java
index 1798f0c210..9f48ac96a3 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java
+++ b/java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security;
+package org.apache.qpid.security;
import java.security.Security;
import java.util.Map;
@@ -26,7 +26,7 @@ import java.util.TreeMap;
import javax.security.sasl.SaslClientFactory;
-import org.apache.qpidity.QpidConfig;
+import org.apache.qpid.QpidConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java b/java/common/src/main/java/org/apache/qpid/security/JCAProvider.java
index c775171a5f..033deb550c 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java
+++ b/java/common/src/main/java/org/apache/qpid/security/JCAProvider.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security;
+package org.apache.qpid.security;
import java.security.Provider;
import java.security.Security;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java
index 0fd647e015..89a63abeab 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java
+++ b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security;
+package org.apache.qpid.security;
import java.io.IOException;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java
index 6e4a0218d2..81acc66de4 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java
+++ b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security.amqplain;
+package org.apache.qpid.security.amqplain;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
diff --git a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java
index abc881f433..6c66c87f4c 100644
--- a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java
+++ b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.security.amqplain;
+package org.apache.qpid.security.amqplain;
import javax.security.sasl.SaslClientFactory;
import javax.security.sasl.SaslClient;
diff --git a/java/common/src/main/java/org/apache/qpid/transport/Binary.java b/java/common/src/main/java/org/apache/qpid/transport/Binary.java
new file mode 100644
index 0000000000..e6dedc536f
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/Binary.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport;
+
+
+/**
+ * Binary
+ *
+ */
+
+public final class Binary
+{
+
+ private byte[] bytes;
+ private int offset;
+ private int size;
+ private int hash = 0;
+
+ public Binary(byte[] bytes, int offset, int size)
+ {
+ if (offset + size > bytes.length)
+ {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ this.bytes = bytes;
+ this.offset = offset;
+ this.size = size;
+ }
+
+ public Binary(byte[] bytes)
+ {
+ this(bytes, 0, bytes.length);
+ }
+
+ public final byte[] array()
+ {
+ return bytes;
+ }
+
+ public final int offset()
+ {
+ return offset;
+ }
+
+ public final int size()
+ {
+ return size;
+ }
+
+ public final Binary slice(int low, int high)
+ {
+ int sz;
+
+ if (high < 0)
+ {
+ sz = size + high;
+ }
+ else
+ {
+ sz = high - low;
+ }
+
+ if (sz < 0)
+ {
+ sz = 0;
+ }
+
+ return new Binary(bytes, offset + low, sz);
+ }
+
+ public final int hashCode()
+ {
+ if (hash == 0)
+ {
+ int hc = 0;
+ for (int i = 0; i < size; i++)
+ {
+ hc = 31*hc + (0xFF & bytes[offset + i]);
+ }
+ hash = hc;
+ }
+
+ return hash;
+ }
+
+ public final boolean equals(Object o)
+ {
+ if (!(o instanceof Binary))
+ {
+ return false;
+ }
+
+ Binary buf = (Binary) o;
+ if (this.size != buf.size)
+ {
+ return false;
+ }
+
+ for (int i = 0; i < size; i++)
+ {
+ if (bytes[offset + i] != buf.bytes[buf.offset + i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Binding.java b/java/common/src/main/java/org/apache/qpid/transport/Binding.java
index 18ed97098d..8418c42189 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Binding.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Binding.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Channel.java b/java/common/src/main/java/org/apache/qpid/transport/Channel.java
index fb8918eb7b..d6b015930b 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Channel.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Channel.java
@@ -18,10 +18,10 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.Frame;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.network.Frame;
+import org.apache.qpid.transport.util.Logger;
import java.nio.ByteBuffer;
@@ -30,8 +30,8 @@ import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import static org.apache.qpidity.transport.network.Frame.*;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.network.Frame.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
@@ -53,10 +53,6 @@ public class Channel extends Invoker
// session may be null
private Session session;
- private Lock commandLock = new ReentrantLock();
- private boolean first = true;
- private ByteBuffer data = null;
-
public Channel(Connection connection, int channel, SessionDelegate delegate)
{
this.connection = connection;
@@ -104,16 +100,6 @@ public class Channel extends Invoker
method.delegate(session, sessionDelegate);
}
- public void header(Void v, Header header)
- {
- header.delegate(session, sessionDelegate);
- }
-
- public void data(Void v, Data data)
- {
- data.delegate(session, sessionDelegate);
- }
-
public void error(Void v, ProtocolError error)
{
throw new RuntimeException(error.getMessage());
@@ -148,58 +134,28 @@ public class Channel extends Invoker
this.session = session;
}
- private void emit(ProtocolEvent event)
- {
- connection.send(new ConnectionEvent(channel, event));
- }
-
- public void method(Method m)
+ void closeCode(ConnectionClose close)
{
- if (m.getEncodedTrack() == Frame.L4)
- {
- commandLock.lock();
- }
-
- emit(m);
-
- if (m.getEncodedTrack() == Frame.L4 && !m.hasPayload())
+ if (session != null)
{
- commandLock.unlock();
+ session.closeCode(close);
}
}
- public void header(Header header)
+ private void emit(ProtocolEvent event)
{
- emit(header);
+ event.setChannel(channel);
+ connection.send(event);
}
- public void data(ByteBuffer buf)
+ public void method(Method m)
{
- if (data != null)
+ emit(m);
+
+ if (!m.isBatch())
{
- emit(new Data(data, first, false));
- first = false;
+ connection.flush();
}
-
- data = buf;
- }
-
- public void data(String str)
- {
- data(str.getBytes());
- }
-
- public void data(byte[] bytes)
- {
- data(ByteBuffer.wrap(bytes));
- }
-
- public void end()
- {
- emit(new Data(data, first, true));
- first = true;
- data = null;
- commandLock.unlock();
}
protected void invoke(Method m)
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java
index 96578ffeb8..8475fbf174 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.UUID;
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
index 699854fb3b..bbdadfadb9 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
@@ -31,10 +31,9 @@ public abstract class ClientDelegate extends ConnectionDelegate
public void init(Channel ch, ProtocolHeader hdr)
{
- if (hdr.getMajor() != TransportConstants.getVersionMajor() &&
- hdr.getMinor() != TransportConstants.getVersionMinor())
+ if (hdr.getMajor() != 0 && hdr.getMinor() != 10)
{
- throw new RuntimeException("version missmatch: " + hdr);
+ throw new ProtocolVersionException(hdr.getMajor(), hdr.getMinor());
}
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Connection.java b/java/common/src/main/java/org/apache/qpid/transport/Connection.java
index 9829343491..68b9b209bb 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Connection.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java
@@ -18,9 +18,9 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.util.Logger;
import java.util.ArrayList;
import java.util.HashMap;
@@ -40,14 +40,13 @@ import java.nio.ByteBuffer;
* short instead of Short
*/
-// RA making this public until we sort out the package issues
public class Connection
- implements Receiver<ConnectionEvent>, Sender<ConnectionEvent>
+ implements Receiver<ProtocolEvent>, Sender<ProtocolEvent>
{
private static final Logger log = Logger.get(Connection.class);
- final private Sender<ConnectionEvent> sender;
+ final private Sender<ProtocolEvent> sender;
final private ConnectionDelegate delegate;
private int channelMax = 1;
// want to make this final
@@ -55,7 +54,7 @@ public class Connection
final private Map<Integer,Channel> channels = new HashMap<Integer,Channel>();
- public Connection(Sender<ConnectionEvent> sender,
+ public Connection(Sender<ProtocolEvent> sender,
ConnectionDelegate delegate)
{
this.sender = sender;
@@ -77,19 +76,25 @@ public class Connection
return delegate;
}
- public void received(ConnectionEvent event)
+ public void received(ProtocolEvent event)
{
log.debug("RECV: [%s] %s", this, event);
Channel channel = getChannel(event.getChannel());
- channel.received(event.getProtocolEvent());
+ channel.received(event);
}
- public void send(ConnectionEvent event)
+ public void send(ProtocolEvent event)
{
log.debug("SEND: [%s] %s", this, event);
sender.send(event);
}
+ public void flush()
+ {
+ log.debug("FLUSH: [%s]", this);
+ sender.flush();
+ }
+
public int getChannelMax()
{
return channelMax;
@@ -143,6 +148,17 @@ public class Connection
delegate.exception(t);
}
+ void closeCode(ConnectionClose close)
+ {
+ synchronized (channels)
+ {
+ for (Channel ch : channels.values())
+ {
+ ch.closeCode(close);
+ }
+ }
+ }
+
public void closed()
{
log.debug("connection closed: %s", this);
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java
index 14344991c6..2aa1db7b28 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.util.Logger;
-import org.apache.qpidity.SecurityHelper;
-import org.apache.qpidity.QpidException;
+import org.apache.qpid.SecurityHelper;
+import org.apache.qpid.QpidException;
import java.io.UnsupportedEncodingException;
@@ -82,28 +82,12 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel>
public void init(Channel ch, ProtocolHeader hdr)
{
- ch.getConnection().send(new ConnectionEvent(0, new ProtocolHeader
- (1,
- TransportConstants.getVersionMajor(),
- TransportConstants.getVersionMinor())));
- if (hdr.getMajor() != TransportConstants.getVersionMajor() &&
- hdr.getMinor() != TransportConstants.getVersionMinor())
- {
- // XXX
- ch.getConnection().send(new ConnectionEvent(0, new ProtocolHeader
- (1,
- TransportConstants.getVersionMajor(),
- TransportConstants.getVersionMinor())));
- ch.getConnection().close();
- }
- else
- {
- List<Object> plain = new ArrayList<Object>();
- plain.add("PLAIN");
- List<Object> utf8 = new ArrayList<Object>();
- utf8.add("utf8");
- ch.connectionStart(null, plain, utf8);
- }
+ ch.getConnection().send(new ProtocolHeader (1, hdr.getMajor(), hdr.getMinor()));
+ List<Object> plain = new ArrayList<Object>();
+ plain.add("PLAIN");
+ List<Object> utf8 = new ArrayList<Object>();
+ utf8.add("utf8");
+ ch.connectionStart(null, plain, utf8);
}
// ----------------------------------------------
@@ -264,6 +248,12 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel>
context.connectionOpenOk(hosts);
}
+ @Override public void connectionClose(Channel ch, ConnectionClose close)
+ {
+ ch.getConnection().closeCode(close);
+ ch.connectionCloseOk();
+ }
+
public String getPassword()
{
return _password;
@@ -294,8 +284,4 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel>
_virtualHost = host;
}
- public String getUnsupportedProtocol()
- {
- return null;
- }
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java
new file mode 100644
index 0000000000..c3239ef684
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport;
+
+
+/**
+ * ConnectionException
+ *
+ */
+
+public class ConnectionException extends RuntimeException
+{
+
+ private ConnectionClose close;
+
+ public ConnectionException(ConnectionClose close)
+ {
+ super(close.getReplyText());
+ this.close = close;
+ }
+
+ public ConnectionClose getClose()
+ {
+ return close;
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Echo.java b/java/common/src/main/java/org/apache/qpid/transport/Echo.java
index 03d0d3e161..b2be32331a 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Echo.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Echo.java
@@ -18,12 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.io.IOException;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.network.mina.MinaHandler;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.io.IoAcceptor;
/**
@@ -34,31 +35,9 @@ import org.apache.qpidity.transport.network.mina.MinaHandler;
public class Echo extends SessionDelegate
{
- private MessageTransfer xfr = null;
-
public void messageTransfer(Session ssn, MessageTransfer xfr)
{
- this.xfr = xfr;
ssn.invoke(xfr);
- }
-
- public void header(Session ssn, Header hdr)
- {
- ssn.header(hdr);
- }
-
- public void data(Session ssn, Data data)
- {
- for (ByteBuffer buf : data.getFragments())
- {
- ssn.data(buf);
- }
- if (data.isLast())
- {
- ssn.endData();
- }
-
- // XXX: should be able to get command-id from any segment
ssn.processed(xfr);
}
@@ -81,7 +60,9 @@ public class Echo extends SessionDelegate
delegate.setUsername("guest");
delegate.setPassword("guest");
- MinaHandler.accept("0.0.0.0", 5672, delegate);
+ IoAcceptor ioa = new IoAcceptor
+ ("0.0.0.0", 5672, new ConnectionBinding(delegate));
+ ioa.start();
}
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Field.java b/java/common/src/main/java/org/apache/qpid/transport/Field.java
index ebbd59288b..bc6bf10041 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Field.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Field.java
@@ -18,10 +18,10 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.codec.Decoder;
-import org.apache.qpidity.transport.codec.Encoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encoder;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Future.java b/java/common/src/main/java/org/apache/qpid/transport/Future.java
index 8936f06831..d8cde61af5 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Future.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Future.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Header.java b/java/common/src/main/java/org/apache/qpid/transport/Header.java
index ae11bb0c69..9439e5e0de 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Header.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Header.java
@@ -18,11 +18,14 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.Frame;
+import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
import java.nio.ByteBuffer;
@@ -32,65 +35,43 @@ import java.nio.ByteBuffer;
* @author Rafael H. Schloming
*/
-public class Header implements ProtocolEvent {
+public class Header {
- private final List<Struct> structs;
- private ByteBuffer _buf;
- private boolean _noPayload;
+ private final Struct[] structs;
- public Header(List<Struct> structs, boolean lastframe)
+ public Header(List<Struct> structs)
{
- this.structs = structs;
- _noPayload= lastframe;
+ this(structs.toArray(new Struct[structs.size()]));
}
- public List<Struct> getStructs()
+ public Header(Struct ... structs)
{
- return structs;
+ this.structs = structs;
}
- public void setBuf(ByteBuffer buf)
+ public Struct[] getStructs()
{
- _buf = buf;
+ return structs;
}
- public ByteBuffer getBuf()
- {
- return _buf;
- }
+
public <T> T get(Class<T> klass)
{
for (Struct st : structs)
{
if (klass.isInstance(st))
{
- return klass.cast(st);
+ return (T) st;
}
}
return null;
}
- public byte getEncodedTrack()
- {
- return Frame.L4;
- }
-
- public <C> void delegate(C context, ProtocolDelegate<C> delegate)
- {
- delegate.header(context, this);
- }
-
- public boolean hasNoPayload()
- {
- return _noPayload;
- }
-
-
public String toString()
{
StringBuffer str = new StringBuffer();
- str.append("Header(");
+ str.append(" Header(");
boolean first = true;
for (Struct s : structs)
{
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Method.java b/java/common/src/main/java/org/apache/qpid/transport/Method.java
index f72ebd570c..6b99f6d5d3 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Method.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Method.java
@@ -18,9 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.Frame;
+
+import java.nio.ByteBuffer;
+
+import static org.apache.qpid.transport.util.Functions.*;
/**
* Method
@@ -40,8 +44,10 @@ public abstract class Method extends Struct implements ProtocolEvent
// XXX: command subclass?
private int id;
+ private int channel;
private boolean idSet = false;
private boolean sync = false;
+ private boolean batch = false;
public final int getId()
{
@@ -54,18 +60,58 @@ public abstract class Method extends Struct implements ProtocolEvent
this.idSet = true;
}
+ public final int getChannel()
+ {
+ return channel;
+ }
+
+ public final void setChannel(int channel)
+ {
+ this.channel = channel;
+ }
+
public final boolean isSync()
{
return sync;
}
- void setSync(boolean value)
+ final void setSync(boolean value)
{
this.sync = value;
}
+ public final boolean isBatch()
+ {
+ return batch;
+ }
+
+ final void setBatch(boolean value)
+ {
+ this.batch = value;
+ }
+
public abstract boolean hasPayload();
+ public Header getHeader()
+ {
+ return null;
+ }
+
+ public void setHeader(Header header)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public ByteBuffer getBody()
+ {
+ return null;
+ }
+
+ public void setBody(ByteBuffer body)
+ {
+ throw new UnsupportedOperationException();
+ }
+
public abstract byte getEncodedTrack();
public abstract <C> void dispatch(C context, MethodDelegate<C> delegate);
@@ -84,33 +130,50 @@ public abstract class Method extends Struct implements ProtocolEvent
public String toString()
{
- if (getEncodedTrack() != Frame.L4)
- {
- return super.toString();
- }
-
StringBuilder str = new StringBuilder();
- if (idSet)
+ str.append("ch=");
+ str.append(channel);
+
+ if (getEncodedTrack() == Frame.L4 && idSet)
{
- str.append("id=");
+ str.append(" id=");
str.append(id);
}
- if (sync)
+ if (sync || batch)
{
- if (str.length() > 0)
+ str.append(" ");
+ str.append("[");
+ if (sync)
{
- str.append(" ");
+ str.append("S");
}
- str.append(" [sync]");
+ if (batch)
+ {
+ str.append("B");
+ }
+ str.append("]");
}
- if (str.length() > 0)
+ str.append(" ");
+ str.append(super.toString());
+ Header hdr = getHeader();
+ if (hdr != null)
{
- str.append(" ");
+ for (Struct st : hdr.getStructs())
+ {
+ str.append("\n ");
+ str.append(st);
+ }
}
- str.append(super.toString());
+ ByteBuffer body = getBody();
+ if (body != null)
+ {
+ str.append("\n body=");
+ str.append(str(body, 64));
+ }
+
return str.toString();
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java
index 028d570416..a90948fc1d 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
@@ -35,10 +35,6 @@ public interface ProtocolDelegate<C>
void command(C context, Method command);
- void header(C context, Header header);
-
- void data(C context, Data data);
-
void error(C context, ProtocolError error);
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java
index 59fc3d2552..bd6ab81997 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java
@@ -18,10 +18,10 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.NetworkDelegate;
-import org.apache.qpidity.transport.network.NetworkEvent;
+import org.apache.qpid.transport.network.NetworkDelegate;
+import org.apache.qpid.transport.network.NetworkEvent;
/**
@@ -30,9 +30,10 @@ import org.apache.qpidity.transport.network.NetworkEvent;
* @author Rafael H. Schloming
*/
-public class ProtocolError implements NetworkEvent, ProtocolEvent
+public final class ProtocolError implements NetworkEvent, ProtocolEvent
{
+ private int channel;
private final byte track;
private final String format;
private final Object[] args;
@@ -44,6 +45,16 @@ public class ProtocolError implements NetworkEvent, ProtocolEvent
this.args = args;
}
+ public int getChannel()
+ {
+ return channel;
+ }
+
+ public void setChannel(int channel)
+ {
+ this.channel = channel;
+ }
+
public byte getEncodedTrack()
{
return track;
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java
index 0b38dc6f28..60234c1537 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
@@ -29,6 +29,10 @@ package org.apache.qpidity.transport;
public interface ProtocolEvent
{
+ int getChannel();
+
+ void setChannel(int channel);
+
byte getEncodedTrack();
<C> void delegate(C context, ProtocolDelegate<C> delegate);
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java
index f9cd6f3947..fa0c1e9c63 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java
@@ -18,13 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.nio.ByteBuffer;
-import org.apache.qpidity.transport.network.NetworkDelegate;
-import org.apache.qpidity.transport.network.NetworkEvent;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.NetworkDelegate;
+import org.apache.qpid.transport.network.NetworkEvent;
+import org.apache.qpid.transport.network.Frame;
/**
@@ -33,9 +33,7 @@ import org.apache.qpidity.transport.network.Frame;
* @author Rafael H. Schloming
*/
-//RA making this public until we sort out the package issues
-
-public class ProtocolHeader implements NetworkEvent, ProtocolEvent
+public final class ProtocolHeader implements NetworkEvent, ProtocolEvent
{
private static final byte[] AMQP = {'A', 'M', 'Q', 'P' };
@@ -44,6 +42,7 @@ public class ProtocolHeader implements NetworkEvent, ProtocolEvent
final private byte instance;
final private byte major;
final private byte minor;
+ private int channel;
public ProtocolHeader(byte instance, byte major, byte minor)
{
@@ -72,6 +71,16 @@ public class ProtocolHeader implements NetworkEvent, ProtocolEvent
return minor;
}
+ public int getChannel()
+ {
+ return channel;
+ }
+
+ public void setChannel(int channel)
+ {
+ this.channel = channel;
+ }
+
public byte getEncodedTrack()
{
return Frame.L1;
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java
index 62d8f4d99d..2de0c169a5 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java
@@ -18,39 +18,35 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
- * ConnectionEvent
+ * ProtocolVersionException
*
*/
-public class ConnectionEvent
+public final class ProtocolVersionException extends TransportException
{
- private final int channel;
- private final ProtocolEvent event;
+ private final byte major;
+ private final byte minor;
- public ConnectionEvent(int channel, ProtocolEvent event)
+ public ProtocolVersionException(byte major, byte minor)
{
- this.channel = channel;
- this.event = event;
+ super(String.format("version missmatch: %s-%s", major, minor));
+ this.major = major;
+ this.minor = minor;
}
- public int getChannel()
+ public byte getMajor()
{
- return channel;
+ return this.major;
}
- public ProtocolEvent getProtocolEvent()
+ public byte getMinor()
{
- return event;
- }
-
- public String toString()
- {
- return String.format("[%d] %s", channel, event);
+ return this.minor;
}
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Range.java b/java/common/src/main/java/org/apache/qpid/transport/Range.java
index 14522cd45f..f4335dc8a6 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Range.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Range.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.ArrayList;
import java.util.List;
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java
index e05e399262..9b2744ee8b 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.Iterator;
import java.util.ListIterator;
@@ -47,6 +47,11 @@ public final class RangeSet implements Iterable<Range>
return ranges.iterator();
}
+ public Range getFirst()
+ {
+ return ranges.getFirst();
+ }
+
public boolean includes(Range range)
{
for (Range r : this)
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Receiver.java b/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
index 8952ebf2a5..2a994580dc 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Receiver.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Result.java b/java/common/src/main/java/org/apache/qpid/transport/Result.java
index 2126a76a53..1116492a8d 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Result.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Result.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Sender.java b/java/common/src/main/java/org/apache/qpid/transport/Sender.java
index 6da8358bd6..9a6f675d7f 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Sender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Sender.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
@@ -31,6 +31,8 @@ public interface Sender<T>
void send(T msg);
+ void flush();
+
void close();
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java
index 988ac4788f..10ca6cfb0a 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Session.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java
@@ -18,12 +18,12 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.Frame;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.util.Logger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -33,9 +33,10 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-import static org.apache.qpidity.transport.Option.*;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.Option.*;
+import static org.apache.qpid.transport.util.Functions.*;
import static org.apache.qpid.util.Serial.*;
+import static org.apache.qpid.util.Strings.*;
/**
* Session
@@ -75,7 +76,8 @@ public class Session extends Invoker
// completed incoming commands
private final Object processedLock = new Object();
private RangeSet processed = new RangeSet();
- private Range syncPoint = null;
+ private int maxProcessed = commandsIn - 1;
+ private int syncPoint = maxProcessed;
// outgoing command count
private int commandsOut = 0;
@@ -127,10 +129,16 @@ public class Session extends Invoker
{
int id = nextCommandId();
cmd.setId(id);
- log.debug("ID: [%s] %s", this.channel, id);
- if ((id % 65536) == 0)
+
+ if(log.isDebugEnabled())
+ {
+ log.debug("ID: [%s] %s", this.channel, id);
+ }
+
+ //if ((id % 65536) == 0)
+ if ((id & 0xff) == 0)
{
- flushProcessed(true);
+ flushProcessed(TIMELY_REPLY);
}
}
@@ -158,7 +166,16 @@ public class Session extends Invoker
synchronized (processedLock)
{
processed.add(range);
- flush = syncPoint != null && processed.includes(syncPoint);
+ Range first = processed.getFirst();
+ int lower = first.getLower();
+ int upper = first.getUpper();
+ int old = maxProcessed;
+ if (le(lower, maxProcessed + 1))
+ {
+ maxProcessed = max(maxProcessed, upper);
+ }
+ flush = lt(old, syncPoint) && ge(maxProcessed, syncPoint);
+ syncPoint = maxProcessed;
}
if (flush)
{
@@ -166,19 +183,14 @@ public class Session extends Invoker
}
}
- public void flushProcessed()
- {
- flushProcessed(false);
- }
-
- private void flushProcessed(boolean timely_reply)
+ public void flushProcessed(Option ... options)
{
RangeSet copy;
synchronized (processedLock)
{
copy = processed.copy();
}
- sessionCompleted(copy, timely_reply ? TIMELY_REPLY : NO_OPTION);
+ sessionCompleted(copy, options);
}
void knownComplete(RangeSet kc)
@@ -204,15 +216,11 @@ public class Session extends Invoker
{
int id = getCommandsIn() - 1;
log.debug("%s synced to %d", this, id);
- Range range = new Range(0, id - 1);
boolean flush;
synchronized (processedLock)
{
- flush = processed.includes(range);
- if (!flush)
- {
- syncPoint = range;
- }
+ syncPoint = id;
+ flush = ge(maxProcessed, syncPoint);
}
if (flush)
{
@@ -236,7 +244,11 @@ public class Session extends Invoker
boolean complete(int lower, int upper)
{
- log.debug("%s complete(%d, %d)", this, lower, upper);
+ //avoid autoboxing
+ if(log.isDebugEnabled())
+ {
+ log.debug("%s complete(%d, %d)", this, lower, upper);
+ }
synchronized (commands)
{
int old = maxComplete;
@@ -254,8 +266,25 @@ public class Session extends Invoker
}
}
- protected void invoke(Method m)
+ public void invoke(Method m)
{
+ if (closed.get())
+ {
+ List<ExecutionException> exc = getExceptions();
+ if (!exc.isEmpty())
+ {
+ throw new SessionException(exc);
+ }
+ else if (close != null)
+ {
+ throw new ConnectionException(close);
+ }
+ else
+ {
+ throw new SessionClosedException();
+ }
+ }
+
if (m.getEncodedTrack() == Frame.L4)
{
synchronized (commands)
@@ -276,7 +305,7 @@ public class Session extends Invoker
}
needSync = !m.isSync();
channel.method(m);
- if (autoSync && !m.hasPayload())
+ if (autoSync)
{
sync();
}
@@ -295,50 +324,6 @@ public class Session extends Invoker
}
}
- public void header(Header header)
- {
- channel.header(header);
- }
-
- public Header header(List<Struct> structs)
- {
- Header res = new Header(structs, false);
- header(res);
- return res;
- }
-
- public Header header(Struct ... structs)
- {
- return header(Arrays.asList(structs));
- }
-
- public void data(ByteBuffer buf)
- {
- channel.data(buf);
- }
-
- public void data(String str)
- {
- channel.data(str);
- }
-
- public void data(byte[] bytes)
- {
- channel.data(bytes);
- }
-
- public void endData()
- {
- channel.end();
- synchronized (commands)
- {
- if (autoSync)
- {
- sync();
- }
- }
- }
-
public void sync()
{
sync(timeout);
@@ -353,9 +338,7 @@ public class Session extends Invoker
if (needSync && lt(maxComplete, point))
{
- ExecutionSync sync = new ExecutionSync();
- sync.setSync(true);
- invoke(sync);
+ executionSync(SYNC);
}
long start = System.currentTimeMillis();
@@ -413,6 +396,13 @@ public class Session extends Invoker
}
}
+ private ConnectionClose close = null;
+
+ void closeCode(ConnectionClose close)
+ {
+ this.close = close;
+ }
+
List<ExecutionException> getExceptions()
{
synchronized (exceptions)
@@ -508,6 +498,26 @@ public class Session extends Invoker
}
+ public final void messageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ byte[] body,
+ Option ... _options) {
+ messageTransfer(destination, acceptMode, acquireMode, header,
+ ByteBuffer.wrap(body), _options);
+ }
+
+ public final void messageTransfer(String destination,
+ MessageAcceptMode acceptMode,
+ MessageAcquireMode acquireMode,
+ Header header,
+ String body,
+ Option ... _options) {
+ messageTransfer(destination, acceptMode, acquireMode, header,
+ toUTF8(body), _options);
+ }
+
public void close()
{
sessionRequestTimeout(0);
diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java b/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java
new file mode 100644
index 0000000000..d2c54cf339
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport;
+
+import java.util.Collections;
+
+
+/**
+ * SessionClosedException
+ *
+ */
+
+public class SessionClosedException extends SessionException
+{
+
+ public SessionClosedException()
+ {
+ super(Collections.EMPTY_LIST);
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
index 0e289c54e9..b91763509c 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java
@@ -18,9 +18,9 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
-import org.apache.qpidity.transport.network.Frame;
+import org.apache.qpid.transport.network.Frame;
/**
@@ -48,10 +48,6 @@ public abstract class SessionDelegate
}
}
- public void header(Session ssn, Header header) { }
-
- public void data(Session ssn, Data data) { }
-
public void error(Session ssn, ProtocolError error) { }
@Override public void executionResult(Session ssn, ExecutionResult result)
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/SessionException.java b/java/common/src/main/java/org/apache/qpid/transport/SessionException.java
index fc866f3694..dc294b2206 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/SessionException.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/SessionException.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.List;
diff --git a/java/common/src/main/java/org/apache/qpid/transport/Sink.java b/java/common/src/main/java/org/apache/qpid/transport/Sink.java
new file mode 100644
index 0000000000..8653acedbe
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/Sink.java
@@ -0,0 +1,137 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.io.IoAcceptor;
+
+/**
+ * Sink
+ *
+ */
+
+public class Sink extends SessionDelegate
+{
+
+ private static final String FORMAT_HDR = "%-12s %-18s %-18s %-18s";
+ private static final String FORMAT_ROW = "SSN#%-8X %-18s %-18s %-18s";
+
+ private long interval = 100000;
+ private long start = System.currentTimeMillis();
+ private long count = 0;
+ private long bytes = 0;
+ private long interval_start = start;
+ private long bytes_start = bytes;
+ private long time = start;
+ private int id = System.identityHashCode(this);
+
+ public Sink()
+ {
+ }
+
+ private double msg_rate()
+ {
+ return 1000 * (double) count / (double) (time - start);
+ }
+
+ private double byte_rate()
+ {
+ return (1000 * (double) bytes / (double) (time - start)) / (1024*1024);
+ }
+
+ private double msg_interval_rate()
+ {
+ return 1000 * (double) interval / (double) (time - interval_start);
+ }
+
+ private double byte_interval_rate()
+ {
+ return (1000 * (double) (bytes - bytes_start) / (double) (time - interval_start)) / (1024*1024);
+ }
+
+ private String rates()
+ {
+ return String.format("%.2f/%.2f", msg_rate(), byte_rate());
+ }
+
+ private String interval_rates()
+ {
+ return String.format("%.2f/%.2f", msg_interval_rate(), byte_interval_rate());
+ }
+
+ private String counts()
+ {
+ return String.format("%d/%.2f", count, ((double) bytes)/(1024*1024));
+ }
+
+ public void messageTransfer(Session ssn, MessageTransfer xfr)
+ {
+ count++;
+ bytes += xfr.getBody().remaining();
+ if ((count % interval) == 0)
+ {
+ time = System.currentTimeMillis();
+ System.out.println
+ (String.format
+ (FORMAT_ROW, id, counts(), rates(), interval_rates()));
+ interval_start = time;
+ bytes_start = bytes;
+ }
+ ssn.processed(xfr);
+ }
+
+ public static final void main(String[] args) throws IOException
+ {
+ ConnectionDelegate delegate = new ConnectionDelegate()
+ {
+
+ public SessionDelegate getSessionDelegate()
+ {
+ return new Sink();
+ }
+
+ public void exception(Throwable t)
+ {
+ t.printStackTrace();
+ }
+
+ public void closed() {}
+ };
+
+ //hack
+ delegate.setUsername("guest");
+ delegate.setPassword("guest");
+
+ IoAcceptor ioa = new IoAcceptor
+ ("0.0.0.0", 5672, new ConnectionBinding(delegate));
+ System.out.println
+ (String.format
+ (FORMAT_HDR, "Session", "Count/MBytes", "Cumulative Rate", "Interval Rate"));
+ System.out.println
+ (String.format
+ (FORMAT_HDR, "-------", "------------", "---------------", "-------------"));
+ ioa.start();
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Struct.java b/java/common/src/main/java/org/apache/qpid/transport/Struct.java
index a15d0a1fb8..22bd9f34ad 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/Struct.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/Struct.java
@@ -18,14 +18,14 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.List;
import java.util.Map;
-import org.apache.qpidity.transport.codec.Decoder;
-import org.apache.qpidity.transport.codec.Encodable;
-import org.apache.qpidity.transport.codec.Encoder;
+import org.apache.qpid.transport.codec.Decoder;
+import org.apache.qpid.transport.codec.Encodable;
+import org.apache.qpid.transport.codec.Encoder;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/TransportException.java b/java/common/src/main/java/org/apache/qpid/transport/TransportException.java
index 593209df82..5ef15154fc 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/TransportException.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/TransportException.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java
index ebfc6b120f..a8a4997ae7 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
import java.io.UnsupportedEncodingException;
@@ -29,11 +29,12 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
-import org.apache.qpidity.transport.Type;
+import org.apache.qpid.transport.Binary;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.Type;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
@@ -45,6 +46,14 @@ import static org.apache.qpidity.transport.util.Functions.*;
abstract class AbstractDecoder implements Decoder
{
+ private final Map<Binary,String> str8cache = new LinkedHashMap<Binary,String>()
+ {
+ @Override protected boolean removeEldestEntry(Map.Entry<Binary,String> me)
+ {
+ return size() > 4*1024;
+ }
+ };
+
protected abstract byte doGet();
protected abstract void doGet(byte[] bytes);
@@ -59,6 +68,13 @@ abstract class AbstractDecoder implements Decoder
doGet(bytes);
}
+ protected Binary get(int size)
+ {
+ byte[] bytes = new byte[size];
+ get(bytes);
+ return new Binary(bytes);
+ }
+
protected short uget()
{
return (short) (0xFF & get());
@@ -105,11 +121,11 @@ abstract class AbstractDecoder implements Decoder
return readUint64();
}
- private static final String decode(byte[] bytes, String charset)
+ private static final String decode(byte[] bytes, int offset, int length, String charset)
{
try
{
- return new String(bytes, charset);
+ return new String(bytes, offset, length, charset);
}
catch (UnsupportedEncodingException e)
{
@@ -117,13 +133,22 @@ abstract class AbstractDecoder implements Decoder
}
}
+ private static final String decode(byte[] bytes, String charset)
+ {
+ return decode(bytes, 0, bytes.length, charset);
+ }
public String readStr8()
{
short size = readUint8();
- byte[] bytes = new byte[size];
- get(bytes);
- return decode(bytes, "UTF-8");
+ Binary bin = get(size);
+ String str = str8cache.get(bin);
+ if (str == null)
+ {
+ str = decode(bin.array(), bin.offset(), bin.size(), "UTF-8");
+ str8cache.put(bin, str);
+ }
+ return str;
}
public String readStr16()
@@ -233,7 +258,19 @@ abstract class AbstractDecoder implements Decoder
public Map<String,Object> readMap()
{
long size = readUint32();
+
+ if (size == 0)
+ {
+ return null;
+ }
+
long count = readUint32();
+
+ if (count == 0)
+ {
+ return Collections.EMPTY_MAP;
+ }
+
Map<String,Object> result = new LinkedHashMap();
for (int i = 0; i < count; i++)
{
@@ -243,13 +280,26 @@ abstract class AbstractDecoder implements Decoder
Object value = read(t);
result.put(key, value);
}
+
return result;
}
public List<Object> readList()
{
long size = readUint32();
+
+ if (size == 0)
+ {
+ return null;
+ }
+
long count = readUint32();
+
+ if (count == 0)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
List<Object> result = new ArrayList();
for (int i = 0; i < count; i++)
{
@@ -264,15 +314,21 @@ abstract class AbstractDecoder implements Decoder
public List<Object> readArray()
{
long size = readUint32();
+
if (size == 0)
{
- return Collections.EMPTY_LIST;
+ return null;
}
byte code = get();
Type t = getType(code);
long count = readUint32();
+ if (count == 0)
+ {
+ return Collections.EMPTY_LIST;
+ }
+
List<Object> result = new ArrayList<Object>();
for (int i = 0; i < count; i++)
{
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
index aa90627943..908d14a307 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
import java.io.UnsupportedEncodingException;
@@ -26,16 +26,17 @@ import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.qpidity.transport.Range;
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
-import org.apache.qpidity.transport.Type;
+import org.apache.qpid.transport.Range;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.Type;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
@@ -64,10 +65,13 @@ abstract class AbstractEncoder implements Encoder
ENCODINGS.put(byte[].class, Type.VBIN32);
}
- protected Sizer sizer()
+ private final Map<String,byte[]> str8cache = new LinkedHashMap<String,byte[]>()
{
- return new SizeEncoder();
- }
+ @Override protected boolean removeEldestEntry(Map.Entry<String,byte[]> me)
+ {
+ return size() > 4*1024;
+ }
+ };
protected abstract void doPut(byte b);
@@ -88,6 +92,15 @@ abstract class AbstractEncoder implements Encoder
put(ByteBuffer.wrap(bytes));
}
+ protected abstract int beginSize8();
+ protected abstract void endSize8(int pos);
+
+ protected abstract int beginSize16();
+ protected abstract void endSize16(int pos);
+
+ protected abstract int beginSize32();
+ protected abstract void endSize32(int pos);
+
public void writeUint8(short b)
{
assert b < 0x100;
@@ -132,23 +145,6 @@ abstract class AbstractEncoder implements Encoder
writeUint64(l);
}
- private static final String checkLength(String s, int n)
- {
- if (s == null)
- {
- return "";
- }
-
- if (s.length() > n)
- {
- throw new IllegalArgumentException("string too long: " + s);
- }
- else
- {
- return s;
- }
- }
-
private static final byte[] encode(String s, String charset)
{
try
@@ -163,16 +159,31 @@ abstract class AbstractEncoder implements Encoder
public void writeStr8(String s)
{
- s = checkLength(s, 255);
- writeUint8((short) s.length());
- put(ByteBuffer.wrap(encode(s, "UTF-8")));
+ if (s == null)
+ {
+ s = "";
+ }
+
+ byte[] bytes = str8cache.get(s);
+ if (bytes == null)
+ {
+ bytes = encode(s, "UTF-8");
+ str8cache.put(s, bytes);
+ }
+ writeUint8((short) bytes.length);
+ put(bytes);
}
public void writeStr16(String s)
{
- s = checkLength(s, 65535);
- writeUint16(s.length());
- put(ByteBuffer.wrap(encode(s, "UTF-8")));
+ if (s == null)
+ {
+ s = "";
+ }
+
+ byte[] bytes = encode(s, "UTF-8");
+ writeUint16(bytes.length);
+ put(bytes);
}
public void writeVbin8(byte[] bytes)
@@ -245,18 +256,10 @@ abstract class AbstractEncoder implements Encoder
}
int width = s.getSizeWidth();
+ int pos = -1;
if (width > 0)
{
- if (empty)
- {
- writeSize(width, 0);
- }
- else
- {
- Sizer sizer = sizer();
- s.write(sizer);
- writeSize(width, sizer.size());
- }
+ pos = beginSize(width);
}
if (type > 0)
@@ -265,6 +268,11 @@ abstract class AbstractEncoder implements Encoder
}
s.write(this);
+
+ if (width > 0)
+ {
+ endSize(width, pos);
+ }
}
public void writeStruct32(Struct s)
@@ -275,12 +283,10 @@ abstract class AbstractEncoder implements Encoder
}
else
{
- Sizer sizer = sizer();
- sizer.writeUint16(s.getEncodedType());
- s.write(sizer);
- writeUint32(sizer.size());
+ int pos = beginSize32();
writeUint16(s.getEncodedType());
s.write(this);
+ endSize32(pos);
}
}
@@ -338,18 +344,13 @@ abstract class AbstractEncoder implements Encoder
public void writeMap(Map<String,Object> map)
{
- if (map == null)
+ int pos = beginSize32();
+ if (map != null)
{
- writeUint32(0);
- return;
+ writeUint32(map.size());
+ writeMapEntries(map);
}
-
- Sizer sizer = sizer();
- sizer.writeMap(map);
- // XXX: - 4
- writeUint32(sizer.size() - 4);
- writeUint32(map.size());
- writeMapEntries(map);
+ endSize32(pos);
}
protected void writeMapEntries(Map<String,Object> map)
@@ -367,12 +368,13 @@ abstract class AbstractEncoder implements Encoder
public void writeList(List<Object> list)
{
- Sizer sizer = sizer();
- sizer.writeList(list);
- // XXX: - 4
- writeUint32(sizer.size() - 4);
- writeUint32(list.size());
- writeListEntries(list);
+ int pos = beginSize32();
+ if (list != null)
+ {
+ writeUint32(list.size());
+ writeListEntries(list);
+ }
+ endSize32(pos);
}
protected void writeListEntries(List<Object> list)
@@ -387,16 +389,12 @@ abstract class AbstractEncoder implements Encoder
public void writeArray(List<Object> array)
{
- if (array == null)
+ int pos = beginSize32();
+ if (array != null)
{
- array = Collections.EMPTY_LIST;
+ writeArrayEntries(array);
}
-
- Sizer sizer = sizer();
- sizer.writeArray(array);
- // XXX: -4
- writeUint32(sizer.size() - 4);
- writeArrayEntries(array);
+ endSize32(pos);
}
protected void writeArrayEntries(List<Object> array)
@@ -458,6 +456,39 @@ abstract class AbstractEncoder implements Encoder
}
}
+ private int beginSize(int width)
+ {
+ switch (width)
+ {
+ case 1:
+ return beginSize8();
+ case 2:
+ return beginSize16();
+ case 4:
+ return beginSize32();
+ default:
+ throw new IllegalStateException("illegal width: " + width);
+ }
+ }
+
+ private void endSize(int width, int pos)
+ {
+ switch (width)
+ {
+ case 1:
+ endSize8(pos);
+ break;
+ case 2:
+ endSize16(pos);
+ break;
+ case 4:
+ endSize32(pos);
+ break;
+ default:
+ throw new IllegalStateException("illegal width: " + width);
+ }
+ }
+
private void writeBytes(Type t, byte[] bytes)
{
writeSize(t, bytes.length);
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java
index cf40cef8bf..dd634eb94a 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java
@@ -18,11 +18,13 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import org.apache.qpid.transport.Binary;
+
/**
* BBDecoder
@@ -33,9 +35,9 @@ import java.nio.ByteOrder;
public final class BBDecoder extends AbstractDecoder
{
- private final ByteBuffer in;
+ private ByteBuffer in;
- public BBDecoder(ByteBuffer in)
+ public void init(ByteBuffer in)
{
this.in = in;
this.in.order(ByteOrder.BIG_ENDIAN);
@@ -51,6 +53,21 @@ public final class BBDecoder extends AbstractDecoder
in.get(bytes);
}
+ protected Binary get(int size)
+ {
+ if (in.hasArray())
+ {
+ byte[] bytes = in.array();
+ Binary bin = new Binary(bytes, in.arrayOffset() + in.position(), size);
+ in.position(in.position() + size);
+ return bin;
+ }
+ else
+ {
+ return super.get(size);
+ }
+ }
+
public boolean hasRemaining()
{
return in.hasRemaining();
diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java
new file mode 100644
index 0000000000..390de881ab
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java
@@ -0,0 +1,232 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.codec;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+/**
+ * BBEncoder
+ *
+ * @author Rafael H. Schloming
+ */
+
+public final class BBEncoder extends AbstractEncoder
+{
+
+ private ByteBuffer out;
+ private int segment;
+
+ public BBEncoder(int capacity) {
+ out = ByteBuffer.allocate(capacity);
+ out.order(ByteOrder.BIG_ENDIAN);
+ segment = 0;
+ }
+
+ public void init()
+ {
+ out.clear();
+ segment = 0;
+ }
+
+ public ByteBuffer segment()
+ {
+ int pos = out.position();
+ out.position(segment);
+ ByteBuffer slice = out.slice();
+ slice.limit(pos - segment);
+ out.position(pos);
+ segment = pos;
+ return slice;
+ }
+
+ private void grow(int size)
+ {
+ ByteBuffer old = out;
+ int capacity = old.capacity();
+ out = ByteBuffer.allocate(Math.max(capacity + size, 2*capacity));
+ out.order(ByteOrder.BIG_ENDIAN);
+ out.put(old);
+ }
+
+ protected void doPut(byte b)
+ {
+ try
+ {
+ out.put(b);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(1);
+ out.put(b);
+ }
+ }
+
+ protected void doPut(ByteBuffer src)
+ {
+ try
+ {
+ out.put(src);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(src.remaining());
+ out.put(src);
+ }
+ }
+
+ protected void put(byte[] bytes)
+ {
+ try
+ {
+ out.put(bytes);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(bytes.length);
+ out.put(bytes);
+ }
+ }
+
+ public void writeUint8(short b)
+ {
+ assert b < 0x100;
+
+ try
+ {
+ out.put((byte) b);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(1);
+ out.put((byte) b);
+ }
+ }
+
+ public void writeUint16(int s)
+ {
+ assert s < 0x10000;
+
+ try
+ {
+ out.putShort((short) s);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(2);
+ out.putShort((short) s);
+ }
+ }
+
+ public void writeUint32(long i)
+ {
+ assert i < 0x100000000L;
+
+ try
+ {
+ out.putInt((int) i);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(4);
+ out.putInt((int) i);
+ }
+ }
+
+ public void writeUint64(long l)
+ {
+ try
+ {
+ out.putLong(l);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(8);
+ out.putLong(l);
+ }
+ }
+
+ public int beginSize8()
+ {
+ int pos = out.position();
+ try
+ {
+ out.put((byte) 0);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(1);
+ out.put((byte) 0);
+ }
+ return pos;
+ }
+
+ public void endSize8(int pos)
+ {
+ int cur = out.position();
+ out.put(pos, (byte) (cur - pos - 1));
+ }
+
+ public int beginSize16()
+ {
+ int pos = out.position();
+ try
+ {
+ out.putShort((short) 0);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(2);
+ out.putShort((short) 0);
+ }
+ return pos;
+ }
+
+ public void endSize16(int pos)
+ {
+ int cur = out.position();
+ out.putShort(pos, (short) (cur - pos - 2));
+ }
+
+ public int beginSize32()
+ {
+ int pos = out.position();
+ try
+ {
+ out.putInt(0);
+ }
+ catch (BufferOverflowException e)
+ {
+ grow(4);
+ out.putInt(0);
+ }
+ return pos;
+ }
+
+ public void endSize32(int pos)
+ {
+ int cur = out.position();
+ out.putInt(pos, (cur - pos - 4));
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java
index dec901748d..50e787ccb2 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java
@@ -18,14 +18,14 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java
index 60c2ea97b8..2aefafd19c 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
index 9d7a1a695d..2d8d13e80a 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
@@ -18,14 +18,14 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.codec;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
/**
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
new file mode 100644
index 0000000000..33d552b91e
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
@@ -0,0 +1,226 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.codec.BBDecoder;
+import org.apache.qpid.transport.codec.Decoder;
+
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.Method;
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.SegmentType;
+import org.apache.qpid.transport.Struct;
+
+
+/**
+ * Assembler
+ *
+ */
+
+public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate
+{
+
+ private final Receiver<ProtocolEvent> receiver;
+ private final Map<Integer,List<Frame>> segments;
+ private final Method[] incomplete;
+ private final ThreadLocal<BBDecoder> decoder = new ThreadLocal<BBDecoder>()
+ {
+ public BBDecoder initialValue()
+ {
+ return new BBDecoder();
+ }
+ };
+
+ public Assembler(Receiver<ProtocolEvent> receiver)
+ {
+ this.receiver = receiver;
+ segments = new HashMap<Integer,List<Frame>>();
+ incomplete = new Method[64*1024];
+ }
+
+ private int segmentKey(Frame frame)
+ {
+ return (frame.getTrack() + 1) * frame.getChannel();
+ }
+
+ private List<Frame> getSegment(Frame frame)
+ {
+ return segments.get(segmentKey(frame));
+ }
+
+ private void setSegment(Frame frame, List<Frame> segment)
+ {
+ int key = segmentKey(frame);
+ if (segments.containsKey(key))
+ {
+ error(new ProtocolError(Frame.L2, "segment in progress: %s",
+ frame));
+ }
+ segments.put(segmentKey(frame), segment);
+ }
+
+ private void clearSegment(Frame frame)
+ {
+ segments.remove(segmentKey(frame));
+ }
+
+ private void emit(int channel, ProtocolEvent event)
+ {
+ event.setChannel(channel);
+ receiver.received(event);
+ }
+
+ public void received(NetworkEvent event)
+ {
+ event.delegate(this);
+ }
+
+ public void exception(Throwable t)
+ {
+ this.receiver.exception(t);
+ }
+
+ public void closed()
+ {
+ this.receiver.closed();
+ }
+
+ public void init(ProtocolHeader header)
+ {
+ emit(0, header);
+ }
+
+ public void error(ProtocolError error)
+ {
+ emit(0, error);
+ }
+
+ public void frame(Frame frame)
+ {
+ ByteBuffer segment;
+ if (frame.isFirstFrame() && frame.isLastFrame())
+ {
+ segment = frame.getBody();
+ assemble(frame, segment);
+ }
+ else
+ {
+ List<Frame> frames;
+ if (frame.isFirstFrame())
+ {
+ frames = new ArrayList<Frame>();
+ setSegment(frame, frames);
+ }
+ else
+ {
+ frames = getSegment(frame);
+ }
+
+ frames.add(frame);
+
+ if (frame.isLastFrame())
+ {
+ clearSegment(frame);
+
+ int size = 0;
+ for (Frame f : frames)
+ {
+ size += f.getSize();
+ }
+ segment = ByteBuffer.allocate(size);
+ for (Frame f : frames)
+ {
+ segment.put(f.getBody());
+ }
+ segment.flip();
+ assemble(frame, segment);
+ }
+ }
+
+ }
+
+ private void assemble(Frame frame, ByteBuffer segment)
+ {
+ BBDecoder dec = decoder.get();
+ dec.init(segment);
+
+ int channel = frame.getChannel();
+ Method command;
+
+ switch (frame.getType())
+ {
+ case CONTROL:
+ int controlType = dec.readUint16();
+ Method control = Method.create(controlType);
+ control.read(dec);
+ emit(channel, control);
+ break;
+ case COMMAND:
+ int commandType = dec.readUint16();
+ // read in the session header, right now we don't use it
+ dec.readUint16();
+ command = Method.create(commandType);
+ command.read(dec);
+ if (command.hasPayload())
+ {
+ incomplete[channel] = command;
+ }
+ else
+ {
+ emit(channel, command);
+ }
+ break;
+ case HEADER:
+ command = incomplete[channel];
+ List<Struct> structs = new ArrayList(2);
+ while (dec.hasRemaining())
+ {
+ structs.add(dec.readStruct32());
+ }
+ command.setHeader(new Header(structs));
+ if (frame.isLastSegment())
+ {
+ incomplete[channel] = null;
+ emit(channel, command);
+ }
+ break;
+ case BODY:
+ command = incomplete[channel];
+ command.setBody(segment);
+ incomplete[channel] = null;
+ emit(channel, command);
+ break;
+ default:
+ throw new IllegalStateException("unknown frame type: " + frame.getType());
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java
index 2e7b41bf42..6886cb3a5a 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java
@@ -18,62 +18,43 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.codec;
+package org.apache.qpid.transport.network;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
/**
- * BBEncoder
+ * ConnectionBinding
*
- * @author Rafael H. Schloming
*/
-public final class BBEncoder extends AbstractEncoder
+public class ConnectionBinding implements Binding<Connection,ByteBuffer>
{
- private final ByteBuffer out;
+ private static final int MAX_FRAME_SIZE = 64 * 1024 - 1;
- public BBEncoder(ByteBuffer out) {
- this.out = out;
- this.out.order(ByteOrder.BIG_ENDIAN);
- }
-
- protected void doPut(byte b)
- {
- out.put(b);
- }
+ private final ConnectionDelegate delegate;
- protected void doPut(ByteBuffer src)
+ public ConnectionBinding(ConnectionDelegate delegate)
{
- out.put(src);
+ this.delegate = delegate;
}
- public void writeUint8(short b)
+ public Connection endpoint(Sender<ByteBuffer> sender)
{
- assert b < 0x100;
-
- out.put((byte) b);
- }
-
- public void writeUint16(int s)
- {
- assert s < 0x10000;
-
- out.putShort((short) s);
- }
-
- public void writeUint32(long i)
- {
- assert i < 0x100000000L;
-
- out.putInt((int) i);
+ // XXX: hardcoded max-frame
+ return new Connection
+ (new Disassembler(sender, MAX_FRAME_SIZE), delegate);
}
- public void writeUint64(long l)
+ public Receiver<ByteBuffer> receiver(Connection conn)
{
- out.putLong(l);
+ return new InputHandler(new Assembler(conn));
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java
new file mode 100644
index 0000000000..bb7d2506e3
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java
@@ -0,0 +1,236 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network;
+
+import org.apache.qpid.transport.codec.BBEncoder;
+
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.Method;
+import org.apache.qpid.transport.ProtocolDelegate;
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.SegmentType;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.Struct;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import static org.apache.qpid.transport.network.Frame.*;
+
+import static java.lang.Math.*;
+
+
+/**
+ * Disassembler
+ *
+ */
+
+public final class Disassembler implements Sender<ProtocolEvent>,
+ ProtocolDelegate<Void>
+{
+
+ private final Sender<ByteBuffer> sender;
+ private final int maxPayload;
+ private final ByteBuffer header;
+ private final Object sendlock = new Object();
+ private final ThreadLocal<BBEncoder> encoder = new ThreadLocal()
+ {
+ public BBEncoder initialValue()
+ {
+ return new BBEncoder(4*1024);
+ }
+ };
+
+ public Disassembler(Sender<ByteBuffer> sender, int maxFrame)
+ {
+ if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024)
+ {
+ throw new IllegalArgumentException
+ ("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame);
+ }
+ this.sender = sender;
+ this.maxPayload = maxFrame - HEADER_SIZE;
+ this.header = ByteBuffer.allocate(HEADER_SIZE);
+ this.header.order(ByteOrder.BIG_ENDIAN);
+
+ }
+
+ public void send(ProtocolEvent event)
+ {
+ event.delegate(null, this);
+ }
+
+ public void flush()
+ {
+ synchronized (sendlock)
+ {
+ sender.flush();
+ }
+ }
+
+ public void close()
+ {
+ synchronized (sendlock)
+ {
+ sender.close();
+ }
+ }
+
+ private final void frame(byte flags, byte type, byte track, int channel, int size, ByteBuffer buf)
+ {
+ synchronized (sendlock)
+ {
+ header.put(0, flags);
+ header.put(1, type);
+ header.putShort(2, (short) (size + HEADER_SIZE));
+ header.put(5, track);
+ header.putShort(6, (short) channel);
+
+ header.rewind();
+
+ sender.send(header);
+
+ int limit = buf.limit();
+ buf.limit(buf.position() + size);
+ sender.send(buf);
+ buf.limit(limit);
+ }
+ }
+
+ private void fragment(byte flags, SegmentType type, ProtocolEvent event,
+ ByteBuffer buf)
+ {
+ byte typeb = (byte) type.getValue();
+ byte track = event.getEncodedTrack() == Frame.L4 ? (byte) 1 : (byte) 0;
+
+ int remaining = buf.remaining();
+ boolean first = true;
+ while (true)
+ {
+ int size = min(maxPayload, remaining);
+ remaining -= size;
+
+ byte newflags = flags;
+ if (first)
+ {
+ newflags |= FIRST_FRAME;
+ first = false;
+ }
+ if (remaining == 0)
+ {
+ newflags |= LAST_FRAME;
+ }
+
+ frame(newflags, typeb, track, event.getChannel(), size, buf);
+
+ if (remaining == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ public void init(Void v, ProtocolHeader header)
+ {
+ synchronized (sendlock)
+ {
+ sender.send(header.toByteBuffer());
+ sender.flush();
+ }
+ }
+
+ public void control(Void v, Method method)
+ {
+ method(method, SegmentType.CONTROL);
+ }
+
+ public void command(Void v, Method method)
+ {
+ method(method, SegmentType.COMMAND);
+ }
+
+ private ByteBuffer copy(ByteBuffer src)
+ {
+ ByteBuffer buf = ByteBuffer.allocate(src.remaining());
+ buf.put(src);
+ buf.flip();
+ return buf;
+ }
+
+ private void method(Method method, SegmentType type)
+ {
+ BBEncoder enc = encoder.get();
+ enc.init();
+ enc.writeUint16(method.getEncodedType());
+ if (type == SegmentType.COMMAND)
+ {
+ if (method.isSync())
+ {
+ enc.writeUint16(0x0101);
+ }
+ else
+ {
+ enc.writeUint16(0x0100);
+ }
+ }
+ method.write(enc);
+ ByteBuffer methodSeg = enc.segment();
+
+ byte flags = FIRST_SEG;
+
+ boolean payload = method.hasPayload();
+ if (!payload)
+ {
+ flags |= LAST_SEG;
+ }
+
+ ByteBuffer headerSeg = null;
+ if (payload)
+ {
+ final Header hdr = method.getHeader();
+ final Struct[] structs = hdr.getStructs();
+
+ for (Struct st : structs)
+ {
+ enc.writeStruct32(st);
+ }
+ headerSeg = enc.segment();
+ }
+
+ synchronized (sendlock)
+ {
+ fragment(flags, type, method, methodSeg);
+ if (payload)
+ {
+ fragment((byte) 0x0, SegmentType.HEADER, method, headerSeg);
+ fragment(LAST_SEG, SegmentType.BODY, method, method.getBody());
+ }
+ }
+ }
+
+ public void error(Void v, ProtocolError error)
+ {
+ throw new IllegalArgumentException("" + error);
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java b/java/common/src/main/java/org/apache/qpid/transport/network/Frame.java
index 2abac382e6..849355276e 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/Frame.java
@@ -18,10 +18,10 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.network;
+package org.apache.qpid.transport.network;
-import org.apache.qpidity.transport.SegmentType;
-import org.apache.qpidity.transport.util.SliceIterator;
+import org.apache.qpid.transport.SegmentType;
+import org.apache.qpid.transport.util.SliceIterator;
import java.nio.ByteBuffer;
@@ -29,7 +29,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
@@ -38,7 +38,7 @@ import static org.apache.qpidity.transport.util.Functions.*;
* @author Rafael H. Schloming
*/
-public final class Frame implements NetworkEvent, Iterable<ByteBuffer>
+public final class Frame implements NetworkEvent
{
public static final int HEADER_SIZE = 12;
@@ -61,23 +61,21 @@ public final class Frame implements NetworkEvent, Iterable<ByteBuffer>
final private SegmentType type;
final private byte track;
final private int channel;
- final private List<ByteBuffer> fragments;
- private int size;
+ final private ByteBuffer body;
- public Frame(byte flags, SegmentType type, byte track, int channel)
+ public Frame(byte flags, SegmentType type, byte track, int channel,
+ ByteBuffer body)
{
this.flags = flags;
this.type = type;
this.track = track;
this.channel = channel;
- this.size = 0;
- this.fragments = new ArrayList<ByteBuffer>();
+ this.body = body;
}
- public void addFragment(ByteBuffer fragment)
+ public ByteBuffer getBody()
{
- fragments.add(fragment);
- size += fragment.remaining();
+ return body.slice();
}
public byte getFlags()
@@ -92,7 +90,7 @@ public final class Frame implements NetworkEvent, Iterable<ByteBuffer>
public int getSize()
{
- return size;
+ return body.remaining();
}
public SegmentType getType()
@@ -130,16 +128,6 @@ public final class Frame implements NetworkEvent, Iterable<ByteBuffer>
return flag(LAST_FRAME);
}
- public Iterator<ByteBuffer> getFragments()
- {
- return new SliceIterator(fragments.iterator());
- }
-
- public Iterator<ByteBuffer> iterator()
- {
- return getFragments();
- }
-
public void delegate(NetworkDelegate delegate)
{
delegate.frame(this);
@@ -148,26 +136,14 @@ public final class Frame implements NetworkEvent, Iterable<ByteBuffer>
public String toString()
{
StringBuilder str = new StringBuilder();
+
str.append(String.format
("[%05d %05d %1d %s %d%d%d%d] ", getChannel(), getSize(),
getTrack(), getType(),
isFirstSegment() ? 1 : 0, isLastSegment() ? 1 : 0,
isFirstFrame() ? 1 : 0, isLastFrame() ? 1 : 0));
- boolean first = true;
- for (ByteBuffer buf : this)
- {
- if (first)
- {
- first = false;
- }
- else
- {
- str.append(" | ");
- }
-
- str.append(str(buf));
- }
+ str.append(str(body));
return str.toString();
}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
new file mode 100644
index 0000000000..408c95e075
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
@@ -0,0 +1,204 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.SegmentType;
+
+import static org.apache.qpid.transport.util.Functions.*;
+
+import static org.apache.qpid.transport.network.InputHandler.State.*;
+
+
+/**
+ * InputHandler
+ *
+ * @author Rafael H. Schloming
+ */
+
+public final class InputHandler implements Receiver<ByteBuffer>
+{
+
+ public enum State
+ {
+ PROTO_HDR,
+ FRAME_HDR,
+ FRAME_BODY,
+ ERROR;
+ }
+
+ private final Receiver<NetworkEvent> receiver;
+ private State state;
+ private ByteBuffer input = null;
+ private int needed;
+
+ private byte flags;
+ private SegmentType type;
+ private byte track;
+ private int channel;
+
+ public InputHandler(Receiver<NetworkEvent> receiver, State state)
+ {
+ this.receiver = receiver;
+ this.state = state;
+
+ switch (state)
+ {
+ case PROTO_HDR:
+ needed = 8;
+ break;
+ case FRAME_HDR:
+ needed = Frame.HEADER_SIZE;
+ break;
+ }
+ }
+
+ public InputHandler(Receiver<NetworkEvent> receiver)
+ {
+ this(receiver, PROTO_HDR);
+ }
+
+ private void error(String fmt, Object ... args)
+ {
+ receiver.received(new ProtocolError(Frame.L1, fmt, args));
+ }
+
+ public void received(ByteBuffer buf)
+ {
+ int limit = buf.limit();
+ int remaining = buf.remaining();
+ while (remaining > 0)
+ {
+ if (remaining >= needed)
+ {
+ int consumed = needed;
+ int pos = buf.position();
+ if (input == null)
+ {
+ buf.limit(pos + needed);
+ input = buf;
+ state = next(pos);
+ buf.limit(limit);
+ buf.position(pos + consumed);
+ }
+ else
+ {
+ buf.limit(pos + needed);
+ input.put(buf);
+ buf.limit(limit);
+ input.flip();
+ state = next(0);
+ }
+
+ remaining -= consumed;
+ input = null;
+ }
+ else
+ {
+ if (input == null)
+ {
+ input = ByteBuffer.allocate(needed);
+ }
+ input.put(buf);
+ needed -= remaining;
+ remaining = 0;
+ }
+ }
+ }
+
+ private State next(int pos)
+ {
+ input.order(ByteOrder.BIG_ENDIAN);
+
+ switch (state) {
+ case PROTO_HDR:
+ if (input.get(pos) != 'A' &&
+ input.get(pos + 1) != 'M' &&
+ input.get(pos + 2) != 'Q' &&
+ input.get(pos + 3) != 'P')
+ {
+ error("bad protocol header: %s", str(input));
+ return ERROR;
+ }
+
+ byte instance = input.get(pos + 5);
+ byte major = input.get(pos + 6);
+ byte minor = input.get(pos + 7);
+ receiver.received(new ProtocolHeader(instance, major, minor));
+ needed = Frame.HEADER_SIZE;
+ return FRAME_HDR;
+ case FRAME_HDR:
+ flags = input.get(pos);
+ type = SegmentType.get(input.get(pos + 1));
+ int size = (0xFFFF & input.getShort(pos + 2));
+ size -= Frame.HEADER_SIZE;
+ if (size < 0 || size > (64*1024 - 12))
+ {
+ error("bad frame size: %d", size);
+ return ERROR;
+ }
+ byte b = input.get(pos + 5);
+ if ((b & 0xF0) != 0) {
+ error("non-zero reserved bits in upper nibble of " +
+ "frame header byte 5: '%x'", b);
+ return ERROR;
+ } else {
+ track = (byte) (b & 0xF);
+ }
+ channel = (0xFFFF & input.getShort(pos + 6));
+ if (size == 0)
+ {
+ Frame frame = new Frame(flags, type, track, channel, ByteBuffer.allocate(0));
+ receiver.received(frame);
+ needed = Frame.HEADER_SIZE;
+ return FRAME_HDR;
+ }
+ else
+ {
+ needed = size;
+ return FRAME_BODY;
+ }
+ case FRAME_BODY:
+ Frame frame = new Frame(flags, type, track, channel, input.slice());
+ receiver.received(frame);
+ needed = Frame.HEADER_SIZE;
+ return FRAME_HDR;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ public void exception(Throwable t)
+ {
+ receiver.exception(t);
+ }
+
+ public void closed()
+ {
+ receiver.closed();
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java
index 48655edd0c..fbdfe6e84c 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java
@@ -18,10 +18,10 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.network;
+package org.apache.qpid.transport.network;
-import org.apache.qpidity.transport.ProtocolError;
-import org.apache.qpidity.transport.ProtocolHeader;
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolHeader;
/**
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java
index 080efee704..91314cd4ad 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.network;
+package org.apache.qpid.transport.network;
/**
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java
new file mode 100644
index 0000000000..b63020913b
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java
@@ -0,0 +1,109 @@
+package org.apache.qpid.transport.network.io;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQMethodBodyFactory;
+import org.apache.qpid.framing.BodyFactory;
+import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.framing.ContentBodyFactory;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.ContentHeaderBodyFactory;
+import org.apache.qpid.framing.HeartbeatBody;
+import org.apache.qpid.framing.HeartbeatBodyFactory;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.Receiver;
+
+public class InputHandler_0_9 implements Receiver<ByteBuffer>
+{
+
+ private AMQVersionAwareProtocolSession _session;
+ private MethodRegistry _registry;
+ private BodyFactory bodyFactory;
+ private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE];
+
+ static
+ {
+ _bodiesSupported[ContentHeaderBody.TYPE] = ContentHeaderBodyFactory.getInstance();
+ _bodiesSupported[ContentBody.TYPE] = ContentBodyFactory.getInstance();
+ _bodiesSupported[HeartbeatBody.TYPE] = new HeartbeatBodyFactory();
+ }
+
+ public InputHandler_0_9(AMQVersionAwareProtocolSession session)
+ {
+ _session = session;
+ _registry = _session.getMethodRegistry();
+ }
+
+ public void closed()
+ {
+ // AS FIXME: implement
+ }
+
+ public void exception(Throwable t)
+ {
+ // TODO: propogate exception to things
+ t.printStackTrace();
+ }
+
+ public void received(ByteBuffer buf)
+ {
+ org.apache.mina.common.ByteBuffer in = org.apache.mina.common.ByteBuffer.wrap(buf);
+ try
+ {
+ final byte type = in.get();
+ if (type == AMQMethodBody.TYPE)
+ {
+ bodyFactory = new AMQMethodBodyFactory(_session);
+ }
+ else
+ {
+ bodyFactory = _bodiesSupported[type];
+ }
+
+ if (bodyFactory == null)
+ {
+ throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null);
+ }
+
+ final int channel = in.getUnsignedShort();
+ final long bodySize = in.getUnsignedInt();
+
+ // bodySize can be zero
+ if ((channel < 0) || (bodySize < 0))
+ {
+ throw new AMQFrameDecodingException(null, "Undecodable frame: type = " + type + " channel = " + channel
+ + " bodySize = " + bodySize, null);
+ }
+
+ AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory);
+
+ byte marker = in.get();
+ if ((marker & 0xFF) != 0xCE)
+ {
+ throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize
+ + " type=" + type, null);
+ }
+
+ try
+ {
+ frame.getBodyFrame().handle(frame.getChannel(), _session);
+ }
+ catch (AMQException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java
new file mode 100644
index 0000000000..c4559ae6b4
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network.io;
+
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.TransportException;
+
+import java.io.IOException;
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * IoAcceptor
+ *
+ */
+
+public class IoAcceptor<E> extends Thread
+{
+
+
+ private ServerSocket socket;
+ private Binding<E,ByteBuffer> binding;
+
+ public IoAcceptor(SocketAddress address, Binding<E,ByteBuffer> binding)
+ throws IOException
+ {
+ socket = new ServerSocket();
+ socket.setReuseAddress(true);
+ socket.bind(address);
+ this.binding = binding;
+
+ setName(String.format("IoAcceptor - %s", socket.getInetAddress()));
+ }
+
+ public IoAcceptor(String host, int port, Binding<E,ByteBuffer> binding)
+ throws IOException
+ {
+ this(new InetSocketAddress(host, port), binding);
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ Socket sock = socket.accept();
+ IoTransport<E> transport = new IoTransport<E>(sock, binding);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
new file mode 100644
index 0000000000..d6d1df573c
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.transport.network.io;
+
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.util.Logger;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * IoReceiver
+ *
+ */
+
+final class IoReceiver extends Thread
+{
+
+ private static final Logger log = Logger.get(IoReceiver.class);
+
+ private final IoTransport transport;
+ private final Receiver<ByteBuffer> receiver;
+ private final int bufferSize;
+ private final Socket socket;
+ private final long timeout;
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+
+ public IoReceiver(IoTransport transport, Receiver<ByteBuffer> receiver,
+ int bufferSize, long timeout)
+ {
+ this.transport = transport;
+ this.receiver = receiver;
+ this.bufferSize = bufferSize;
+ this.socket = transport.getSocket();
+ this.timeout = timeout;
+
+ setDaemon(true);
+ setName(String.format("IoReceiver - %s", socket.getRemoteSocketAddress()));
+ start();
+ }
+
+ void close()
+ {
+ if (!closed.getAndSet(true))
+ {
+ try
+ {
+ socket.shutdownInput();
+ if (Thread.currentThread() != this)
+ {
+ join(timeout);
+ if (isAlive())
+ {
+ throw new TransportException("join timed out");
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ throw new TransportException(e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+ }
+ }
+
+ public void run()
+ {
+ final int threshold = bufferSize / 2;
+
+ // I set the read buffer size simillar to SO_RCVBUF
+ // Haven't tested with a lower value to see if it's better or worse
+ byte[] buffer = new byte[bufferSize];
+ try
+ {
+ InputStream in = socket.getInputStream();
+ int read = 0;
+ int offset = 0;
+ while ((read = in.read(buffer, offset, bufferSize-offset)) != -1)
+ {
+ if (read > 0)
+ {
+ ByteBuffer b = ByteBuffer.wrap(buffer,offset,read);
+ receiver.received(b);
+ offset+=read;
+ if (offset > threshold)
+ {
+ offset = 0;
+ buffer = new byte[bufferSize];
+ }
+ }
+ }
+ }
+ catch (Throwable t)
+ {
+ receiver.exception(t);
+ }
+ finally
+ {
+ receiver.closed();
+ transport.getSender().close();
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
new file mode 100644
index 0000000000..ef892744ab
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
@@ -0,0 +1,291 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.transport.network.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.util.Logger;
+
+import static org.apache.qpid.transport.util.Functions.*;
+
+
+public final class IoSender extends Thread implements Sender<ByteBuffer>
+{
+
+ private static final Logger log = Logger.get(IoSender.class);
+
+ // by starting here, we ensure that we always test the wraparound
+ // case, we should probably make this configurable somehow so that
+ // we can test other cases as well
+ private final static int START = Integer.MAX_VALUE - 10;
+
+ private final IoTransport transport;
+ private final long timeout;
+ private final Socket socket;
+ private final OutputStream out;
+
+ private final byte[] buffer;
+ private volatile int head = START;
+ private volatile int tail = START;
+ private volatile boolean idle = true;
+ private final Object notFull = new Object();
+ private final Object notEmpty = new Object();
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+
+ private volatile Throwable exception = null;
+
+
+ public IoSender(IoTransport transport, int bufferSize, long timeout)
+ {
+ this.transport = transport;
+ this.socket = transport.getSocket();
+ this.buffer = new byte[pof2(bufferSize)]; // buffer size must be a power of 2
+ this.timeout = timeout;
+
+ try
+ {
+ out = socket.getOutputStream();
+ }
+ catch (IOException e)
+ {
+ throw new TransportException("Error getting output stream for socket", e);
+ }
+
+ setDaemon(true);
+ setName(String.format("IoSender - %s", socket.getRemoteSocketAddress()));
+ start();
+ }
+
+ private static final int pof2(int n)
+ {
+ int result = 1;
+ while (result < n)
+ {
+ result *= 2;
+ }
+ return result;
+ }
+
+ private static final int mod(int n, int m)
+ {
+ int r = n % m;
+ return r < 0 ? m + r : r;
+ }
+
+ public void send(ByteBuffer buf)
+ {
+ if (closed.get())
+ {
+ throw new TransportException("sender is closed", exception);
+ }
+
+ final int size = buffer.length;
+ int remaining = buf.remaining();
+
+ while (remaining > 0)
+ {
+ final int hd = head;
+ final int tl = tail;
+
+ if (hd - tl >= size)
+ {
+ flush();
+ synchronized (notFull)
+ {
+ long start = System.currentTimeMillis();
+ long elapsed = 0;
+ while (!closed.get() && head - tail >= size && elapsed < timeout)
+ {
+ try
+ {
+ notFull.wait(timeout - elapsed);
+ }
+ catch (InterruptedException e)
+ {
+ // pass
+ }
+ elapsed += System.currentTimeMillis() - start;
+ }
+
+ if (closed.get())
+ {
+ throw new TransportException("sender is closed", exception);
+ }
+
+ if (head - tail >= size)
+ {
+ throw new TransportException(String.format("write timed out: %s, %s", head, tail));
+ }
+ }
+ continue;
+ }
+
+ final int hd_idx = mod(hd, size);
+ final int tl_idx = mod(tl, size);
+ final int length;
+
+ if (tl_idx > hd_idx)
+ {
+ length = Math.min(tl_idx - hd_idx, remaining);
+ }
+ else
+ {
+ length = Math.min(size - hd_idx, remaining);
+ }
+
+ buf.get(buffer, hd_idx, length);
+ head += length;
+ remaining -= length;
+ }
+ }
+
+ public void flush()
+ {
+ if (idle)
+ {
+ synchronized (notEmpty)
+ {
+ notEmpty.notify();
+ }
+ }
+ }
+
+ public void close()
+ {
+ close(true);
+ }
+
+ void close(boolean reportException)
+ {
+ if (!closed.getAndSet(true))
+ {
+ synchronized (notEmpty)
+ {
+ notEmpty.notify();
+ }
+
+ try
+ {
+ if (Thread.currentThread() != this)
+ {
+ join(timeout);
+ if (isAlive())
+ {
+ throw new TransportException("join timed out");
+ }
+ }
+ transport.getReceiver().close();
+ socket.close();
+ }
+ catch (InterruptedException e)
+ {
+ throw new TransportException(e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException(e);
+ }
+
+ if (reportException && exception != null)
+ {
+ throw new TransportException(exception);
+ }
+ }
+ }
+
+ public void run()
+ {
+ final int size = buffer.length;
+
+ while (true)
+ {
+ final int hd = head;
+ final int tl = tail;
+
+ if (hd == tl)
+ {
+ if (closed.get())
+ {
+ break;
+ }
+
+ idle = true;
+
+ synchronized (notEmpty)
+ {
+ while (head == tail && !closed.get())
+ {
+ try
+ {
+ notEmpty.wait();
+ }
+ catch (InterruptedException e)
+ {
+ // pass
+ }
+ }
+ }
+
+ idle = false;
+
+ continue;
+ }
+
+ final int hd_idx = mod(hd, size);
+ final int tl_idx = mod(tl, size);
+
+ final int length;
+ if (tl_idx < hd_idx)
+ {
+ length = hd_idx - tl_idx;
+ }
+ else
+ {
+ length = size - tl_idx;
+ }
+
+ try
+ {
+ out.write(buffer, tl_idx, length);
+ }
+ catch (IOException e)
+ {
+ log.error(e, "error in write thread");
+ exception = e;
+ close(false);
+ break;
+ }
+ tail += length;
+ if (head - tl >= size)
+ {
+ synchronized (notFull)
+ {
+ notFull.notify();
+ }
+ }
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java
new file mode 100644
index 0000000000..70fd8a3c06
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.qpid.transport.network.io;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * This class provides a socket based transport using the java.io
+ * classes.
+ *
+ * The following params are configurable via JVM arguments
+ * TCP_NO_DELAY - amqj.tcpNoDelay
+ * SO_RCVBUF - amqj.receiveBufferSize
+ * SO_SNDBUF - amqj.sendBufferSize
+ */
+public final class IoTransport<E>
+{
+
+ static
+ {
+ org.apache.mina.common.ByteBuffer.setAllocator
+ (new org.apache.mina.common.SimpleByteBufferAllocator());
+ org.apache.mina.common.ByteBuffer.setUseDirectBuffers
+ (Boolean.getBoolean("amqj.enableDirectBuffers"));
+ }
+
+ private static final Logger log = Logger.get(IoTransport.class);
+
+ private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024;
+ private static int readBufferSize = Integer.getInteger
+ ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
+ private static int writeBufferSize = Integer.getInteger
+ ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
+
+ private Socket socket;
+ private IoSender sender;
+ private E endpoint;
+ private IoReceiver receiver;
+ private long timeout = 60000;
+
+ IoTransport(Socket socket, Binding<E,ByteBuffer> binding)
+ {
+ this.socket = socket;
+ this.sender = new IoSender(this, 2*writeBufferSize, timeout);
+ this.endpoint = binding.endpoint(sender);
+ this.receiver = new IoReceiver(this, binding.receiver(endpoint),
+ 2*readBufferSize, timeout);
+ }
+
+ IoSender getSender()
+ {
+ return sender;
+ }
+
+ IoReceiver getReceiver()
+ {
+ return receiver;
+ }
+
+ Socket getSocket()
+ {
+ return socket;
+ }
+
+ public static final <E> E connect(String host, int port,
+ Binding<E,ByteBuffer> binding)
+ {
+ Socket socket = createSocket(host, port);
+ IoTransport<E> transport = new IoTransport<E>(socket, binding);
+ return transport.endpoint;
+ }
+
+ public static final Connection connect(String host, int port,
+ ConnectionDelegate delegate)
+ {
+ return connect(host, port, new ConnectionBinding(delegate));
+ }
+
+ public static void connect_0_9(AMQVersionAwareProtocolSession session, String host, int port)
+ {
+ connect(host, port, new Binding_0_9(session));
+ }
+
+ private static class Binding_0_9
+ implements Binding<AMQVersionAwareProtocolSession,ByteBuffer>
+ {
+
+ private AMQVersionAwareProtocolSession session;
+
+ Binding_0_9(AMQVersionAwareProtocolSession session)
+ {
+ this.session = session;
+ }
+
+ public AMQVersionAwareProtocolSession endpoint(Sender<ByteBuffer> sender)
+ {
+ session.setSender(sender);
+ return session;
+ }
+
+ public Receiver<ByteBuffer> receiver(AMQVersionAwareProtocolSession ssn)
+ {
+ return new InputHandler_0_9(ssn);
+ }
+
+ }
+
+ private static Socket createSocket(String host, int port)
+ {
+ try
+ {
+ InetAddress address = InetAddress.getByName(host);
+ Socket socket = new Socket();
+ socket.setReuseAddress(true);
+ socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay"));
+
+ log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize());
+
+ socket.setSendBufferSize(writeBufferSize);
+ socket.setReceiveBufferSize(readBufferSize);
+
+ log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize());
+ log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize());
+
+ socket.connect(new InetSocketAddress(address, port));
+ return socket;
+ }
+ catch (SocketException e)
+ {
+ throw new TransportException("Error connecting to broker", e);
+ }
+ catch (IOException e)
+ {
+ throw new TransportException("Error connecting to broker", e);
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java
index c6855e3d48..f8dbec3c3d 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.network.mina;
+package org.apache.qpid.transport.network.mina;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -33,20 +33,20 @@ import org.apache.mina.filter.ReadThrottleFilterBuilder;
import org.apache.mina.filter.WriteBufferLimitFilterBuilder;
import org.apache.mina.filter.executor.ExecutorFilter;
-import org.apache.qpidity.transport.Binding;
-import org.apache.qpidity.transport.Connection;
-import org.apache.qpidity.transport.ConnectionDelegate;
-import org.apache.qpidity.transport.Receiver;
-import org.apache.qpidity.transport.Sender;
+import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.ConnectionBinding;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.util.Logger;
-import org.apache.qpidity.transport.network.Assembler;
-import org.apache.qpidity.transport.network.Disassembler;
-import org.apache.qpidity.transport.network.InputHandler;
-import org.apache.qpidity.transport.network.OutputHandler;
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
-import static org.apache.qpidity.transport.util.Functions.*;
+import static org.apache.qpid.transport.util.Functions.*;
/**
* MinaHandler
@@ -56,7 +56,6 @@ import static org.apache.qpidity.transport.util.Functions.*;
//RA making this public until we sort out the package issues
public class MinaHandler<E> implements IoHandler
{
- private static final int MAX_FRAME_SIZE = 64 * 1024 - 1;
/** Default buffer size for pending messages reads */
private static final String DEFAULT_READ_BUFFER_LIMIT = "262144";
/** Default buffer size for pending messages writes */
@@ -202,7 +201,7 @@ public class MinaHandler<E> implements IoHandler
IoAcceptor acceptor = new SocketAcceptor();
acceptor.bind(address, new MinaHandler<E>(binding));
}
-
+
public static final <E> E connect(String host, int port,
Binding<E,java.nio.ByteBuffer> binding)
{
@@ -263,43 +262,13 @@ public class MinaHandler<E> implements IoHandler
ConnectionDelegate delegate)
throws IOException
{
- accept(host, port, new ConnectionBinding
- (delegate, InputHandler.State.PROTO_HDR));
+ accept(host, port, new ConnectionBinding(delegate));
}
public static final Connection connect(String host, int port,
ConnectionDelegate delegate)
{
- return connect(host, port, new ConnectionBinding
- (delegate, InputHandler.State.PROTO_HDR));
- }
-
- private static class ConnectionBinding
- implements Binding<Connection,java.nio.ByteBuffer>
- {
-
- private final ConnectionDelegate delegate;
- private final InputHandler.State state;
-
- ConnectionBinding(ConnectionDelegate delegate,
- InputHandler.State state)
- {
- this.delegate = delegate;
- this.state = state;
- }
-
- public Connection endpoint(Sender<java.nio.ByteBuffer> sender)
- {
- // XXX: hardcoded max-frame
- return new Connection
- (new Disassembler(new OutputHandler(sender), MAX_FRAME_SIZE), delegate);
- }
-
- public Receiver<java.nio.ByteBuffer> receiver(Connection conn)
- {
- return new InputHandler(new Assembler(conn), state);
- }
-
+ return connect(host, port, new ConnectionBinding(delegate));
}
}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java
index f0f5731037..69d4061e0c 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java
@@ -18,15 +18,15 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.network.mina;
+package org.apache.qpid.transport.network.mina;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.CloseFuture;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.WriteFuture;
-import org.apache.qpidity.transport.Sender;
-import org.apache.qpidity.transport.TransportException;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
/**
@@ -58,6 +58,11 @@ public class MinaSender implements Sender<java.nio.ByteBuffer>
}
}
+ public void flush()
+ {
+ // pass
+ }
+
public synchronized void close()
{
// MINA will sometimes throw away in-progress writes when you
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java
index a7339427c7..51e41b26f7 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java
@@ -1,4 +1,4 @@
-package org.apache.qpidity.transport.network.nio;
+package org.apache.qpid.transport.network.nio;
import java.io.EOFException;
import java.io.IOException;
@@ -11,13 +11,12 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.qpidity.transport.Connection;
-import org.apache.qpidity.transport.ConnectionDelegate;
-import org.apache.qpidity.transport.Receiver;
-import org.apache.qpidity.transport.network.Assembler;
-import org.apache.qpidity.transport.network.Disassembler;
-import org.apache.qpidity.transport.network.InputHandler;
-import org.apache.qpidity.transport.network.OutputHandler;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionDelegate;
+import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.InputHandler;
public class NioHandler implements Runnable
{
@@ -68,8 +67,7 @@ public class NioHandler implements Runnable
NioSender sender = new NioSender(_ch);
Connection con = new Connection
- (new Disassembler(new OutputHandler(sender), 64*1024 - 1),
- delegate);
+ (new Disassembler(sender, 64*1024 - 1), delegate);
con.setConnectionId(_count.incrementAndGet());
_handlers.put(con.getConnectionId(),sender);
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java
index 2cfe6c2089..33e888cc56 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java
@@ -1,9 +1,9 @@
-package org.apache.qpidity.transport.network.nio;
+package org.apache.qpid.transport.network.nio;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
-import org.apache.qpidity.transport.Sender;
+import org.apache.qpid.transport.Sender;
public class NioSender implements Sender<java.nio.ByteBuffer>
{
@@ -47,6 +47,11 @@ public class NioSender implements Sender<java.nio.ByteBuffer>
}
}
+ public void flush()
+ {
+ // pass
+ }
+
private void write(java.nio.ByteBuffer buf)
{
synchronized (lock)
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java b/java/common/src/main/java/org/apache/qpid/transport/util/Functions.java
index 0038cdf118..2c6984e302 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/util/Functions.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.util;
+package org.apache.qpid.transport.util;
import java.nio.ByteBuffer;
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java b/java/common/src/main/java/org/apache/qpid/transport/util/Logger.java
index 0159036a34..8c4818df92 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/util/Logger.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.util;
+package org.apache.qpid.transport.util;
import org.slf4j.LoggerFactory;
@@ -42,6 +42,11 @@ public final class Logger
this.log = log;
}
+ public boolean isDebugEnabled()
+ {
+ return log.isDebugEnabled();
+ }
+
public void debug(String message, Object ... args)
{
if (log.isDebugEnabled())
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java b/java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java
index 32392a3561..3db29847b2 100644
--- a/java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java
+++ b/java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport.util;
+package org.apache.qpid.transport.util;
import java.nio.ByteBuffer;
diff --git a/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java b/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java
index 2cf035f601..f12fb2cff2 100644
--- a/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java
+++ b/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java
@@ -17,7 +17,7 @@
*/
package org.apache.qpid.url;
-import org.apache.qpidity.exchange.ExchangeDefaults;
+import org.apache.qpid.exchange.ExchangeDefaults;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
diff --git a/java/common/src/main/java/org/apache/qpid/url/QpidURL.java b/java/common/src/main/java/org/apache/qpid/url/QpidURL.java
index 1d94b31de2..5ab4425323 100644
--- a/java/common/src/main/java/org/apache/qpid/url/QpidURL.java
+++ b/java/common/src/main/java/org/apache/qpid/url/QpidURL.java
@@ -17,7 +17,7 @@
*/
package org.apache.qpid.url;
-import org.apache.qpidity.BrokerDetails;
+import org.apache.qpid.BrokerDetails;
import java.util.List;
diff --git a/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java b/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java
index b4a55e2bf4..f92934db7f 100644
--- a/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java
+++ b/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java
@@ -17,8 +17,8 @@
*/
package org.apache.qpid.url;
-import org.apache.qpidity.BrokerDetails;
-import org.apache.qpidity.BrokerDetailsImpl;
+import org.apache.qpid.BrokerDetails;
+import org.apache.qpid.BrokerDetailsImpl;
import java.net.MalformedURLException;
import java.util.ArrayList;
diff --git a/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java
new file mode 100644
index 0000000000..e764c8536b
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+
+/**
+ * NameUUIDGen
+ *
+ */
+
+public final class NameUUIDGen implements UUIDGen
+{
+
+ private static final int WIDTH = 8;
+
+ final private byte[] seed;
+ final private ByteBuffer seedBuf;
+ private long counter;
+
+ public NameUUIDGen()
+ {
+ String namespace = UUID.randomUUID().toString();
+ this.seed = new byte[namespace.length() + WIDTH];
+ for (int i = WIDTH; i < seed.length; i++)
+ {
+ seed[i] = (byte) namespace.charAt(i - WIDTH);
+ }
+ this.seedBuf = ByteBuffer.wrap(seed);
+ this.counter = 0;
+ }
+
+ public UUID generate()
+ {
+ seedBuf.putLong(0, counter++);
+ return UUID.nameUUIDFromBytes(seed);
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java
new file mode 100644
index 0000000000..60b402a105
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.util.UUID;
+
+
+/**
+ * RandomUUIDGen
+ *
+ */
+
+public final class RandomUUIDGen implements UUIDGen
+{
+
+ public UUID generate()
+ {
+ return UUID.randomUUID();
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/util/Strings.java b/java/common/src/main/java/org/apache/qpid/util/Strings.java
new file mode 100644
index 0000000000..4b199bafe6
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/Strings.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.io.UnsupportedEncodingException;
+
+
+/**
+ * Strings
+ *
+ */
+
+public final class Strings
+{
+
+ private static final byte[] EMPTY = new byte[0];
+
+ private static final ThreadLocal<char[]> charbuf = new ThreadLocal()
+ {
+ public char[] initialValue()
+ {
+ return new char[4096];
+ }
+ };
+
+ public static final byte[] toUTF8(String str)
+ {
+ if (str == null)
+ {
+ return EMPTY;
+ }
+ else
+ {
+ final int size = str.length();
+ char[] chars = charbuf.get();
+ if (size > chars.length)
+ {
+ chars = new char[Math.max(size, 2*chars.length)];
+ charbuf.set(chars);
+ }
+
+ str.getChars(0, size, chars, 0);
+ final byte[] bytes = new byte[size];
+ for (int i = 0; i < size; i++)
+ {
+ if (chars[i] > 127)
+ {
+ try
+ {
+ return str.getBytes("UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ bytes[i] = (byte) chars[i];
+ }
+ return bytes;
+ }
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java
new file mode 100644
index 0000000000..3cfe5afdac
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+
+import java.util.UUID;
+
+/**
+ * UUIDGen
+ *
+ */
+
+public interface UUIDGen
+{
+
+ public UUID generate();
+
+}
diff --git a/java/client/src/test/java/org/apache/qpid/testutil/VMBrokerSetup.java b/java/common/src/main/java/org/apache/qpid/util/UUIDs.java
index cedf1ac824..4bf6b7f0a2 100644
--- a/java/client/src/test/java/org/apache/qpid/testutil/VMBrokerSetup.java
+++ b/java/common/src/main/java/org/apache/qpid/util/UUIDs.java
@@ -1,4 +1,5 @@
/*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -6,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,36 +18,42 @@
* under the License.
*
*/
-package org.apache.qpid.testutil;
+package org.apache.qpid.util;
-import junit.extensions.TestSetup;
-import junit.framework.Test;
-import org.apache.qpid.client.transport.TransportConnection;
+/**
+ * UUIDs
+ *
+ */
-public class VMBrokerSetup extends TestSetup
+public final class UUIDs
{
- public VMBrokerSetup(Test t)
+
+ public static final UUIDGen newGenerator()
{
- super(t);
+ return newGenerator(System.getProperty("qpid.uuid.generator",
+ NameUUIDGen.class.getName()));
}
- protected void setUp() throws Exception
+ public static UUIDGen newGenerator(String name)
{
- super.setUp();
try
{
- TransportConnection.createVMBroker(1);
+ Class cls = Class.forName(name);
+ return (UUIDGen) cls.newInstance();
}
- catch (Exception e)
+ catch (InstantiationException e)
{
- fail("Unable to create broker: " + e);
+ throw new RuntimeException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException(e);
}
}
- protected void tearDown() throws Exception
- {
- TransportConnection.killVMBroker(1);
- super.tearDown();
- }
}
diff --git a/java/common/src/main/java/org/apache/qpidity/ProtocolException.java b/java/common/src/main/java/org/apache/qpidity/ProtocolException.java
deleted file mode 100644
index 596143a1b9..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/ProtocolException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.qpidity;
-
-public class ProtocolException extends QpidException
-{
- /**
- * Constructor for a Ptotocol Exception.
- * <p> This is the only provided constructor and the parameters have to be set to null when
- * they are unknown.
- * @param message A description of the reason of this exception.
- * @param errorCode A string specifyin the error code of this exception.
- * @param cause The linked Execption.
- *
- */
- public ProtocolException(String message, ErrorCode errorCode, Throwable cause)
- {
- super(message, errorCode, cause);
- }
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java b/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java
deleted file mode 100644
index a99ea56d69..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpidity.exchange;
-
-/**
- * Default exchange names
- */
-public class ExchangeDefaults
-{
- /** The default direct exchange, which is a special internal exchange that cannot be explicitly bound to. */
- public static final String DEFAULT_EXCHANGE_NAME = "<<default>>";
-
- /** The pre-defined topic exchange, the broker SHOULD provide this. */
- public static final String TOPIC_EXCHANGE_NAME = "amq.topic";
-
- /** Defines the identifying type name of topic exchanges. */
- public static final String TOPIC_EXCHANGE_CLASS = "topic";
-
- /** The pre-defined direct exchange, the broker MUST provide this. */
- public static final String DIRECT_EXCHANGE_NAME = "amq.direct";
-
- /** Defines the identifying type name of direct exchanges. */
- public static final String DIRECT_EXCHANGE_CLASS = "direct";
-
- /** The pre-defined headers exchange, the specification does not say this needs to be provided. */
- public static final String HEADERS_EXCHANGE_NAME = "amq.match";
-
- /** Defines the identifying type name of headers exchanges. */
- public static final String HEADERS_EXCHANGE_CLASS = "headers";
-
- /** The pre-defined fanout exchange, the boker MUST provide this. */
- public static final String FANOUT_EXCHANGE_NAME = "amq.fanout";
-
- /** Defines the identifying type name of fanout exchanges. */
- public static final String FANOUT_EXCHANGE_CLASS = "fanout";
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Data.java b/java/common/src/main/java/org/apache/qpidity/transport/Data.java
deleted file mode 100644
index 4f61380809..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/Data.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport;
-
-import org.apache.qpidity.transport.network.Frame;
-
-import java.nio.ByteBuffer;
-
-import java.util.Collections;
-
-import static org.apache.qpidity.transport.util.Functions.*;
-
-
-/**
- * Data
- *
- */
-
-public class Data implements ProtocolEvent
-{
-
- private final Iterable<ByteBuffer> fragments;
- private final boolean first;
- private final boolean last;
-
- public Data(Iterable<ByteBuffer> fragments, boolean first, boolean last)
- {
- this.fragments = fragments;
- this.first = first;
- this.last = last;
- }
-
- public Data(ByteBuffer buf, boolean first, boolean last)
- {
- this(Collections.singletonList(buf), first, last);
- }
-
- public Iterable<ByteBuffer> getFragments()
- {
- return fragments;
- }
-
- public boolean isFirst()
- {
- return first;
- }
-
- public boolean isLast()
- {
- return last;
- }
-
- public byte getEncodedTrack()
- {
- return Frame.L4;
- }
-
- public <C> void delegate(C context, ProtocolDelegate<C> delegate)
- {
- delegate.data(context, this);
- }
-
- public String toString()
- {
- StringBuffer str = new StringBuffer();
- str.append("Data(");
- boolean first = true;
- int left = 64;
- for (ByteBuffer buf : getFragments())
- {
- if (first)
- {
- first = false;
- }
- else
- {
- str.append(" | ");
- }
- str.append(str(buf, left));
- left -= buf.remaining();
- if (left < 0)
- {
- break;
- }
- }
- str.append(")");
- return str.toString();
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java b/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java
deleted file mode 100644
index e9a0705de0..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.apache.qpidity.transport;
-
-public class TransportConstants
-{
-
- private static byte _protocol_version_minor = 10;
- private static byte _protocol_version_major = 0;
-
- public static void setVersionMajor(byte value)
- {
- _protocol_version_major = value;
- }
-
- public static void setVersionMinor(byte value)
- {
- _protocol_version_minor = value;
- }
-
- public static byte getVersionMajor()
- {
- return _protocol_version_major;
- }
-
- public static byte getVersionMinor()
- {
- return _protocol_version_minor;
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java
deleted file mode 100644
index 474211ced2..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.codec;
-
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-
-import java.util.Iterator;
-
-import static java.lang.Math.*;
-
-
-/**
- * FragmentDecoder
- *
- * @author Rafael H. Schloming
- */
-
-public class FragmentDecoder extends AbstractDecoder
-{
-
- private final Iterator<ByteBuffer> fragments;
- private ByteBuffer current;
-
- public FragmentDecoder(Iterator<ByteBuffer> fragments)
- {
- this.fragments = fragments;
- this.current = null;
- }
-
- public boolean hasRemaining()
- {
- advance();
- return current != null || fragments.hasNext();
- }
-
- private void advance()
- {
- while (current == null && fragments.hasNext())
- {
- current = fragments.next();
- if (current.hasRemaining())
- {
- break;
- }
- else
- {
- current = null;
- }
- }
- }
-
- private void preRead()
- {
- advance();
-
- if (current == null)
- {
- throw new BufferUnderflowException();
- }
- }
-
- private void postRead()
- {
- if (current.remaining() == 0)
- {
- current = null;
- }
- }
-
- protected byte doGet()
- {
- preRead();
- byte b = current.get();
- postRead();
- return b;
- }
-
- protected void doGet(byte[] bytes)
- {
- int remaining = bytes.length;
- int offset = 0;
- while (remaining > 0)
- {
- preRead();
- int size = min(remaining, current.remaining());
- current.get(bytes, offset, size);
- offset += size;
- remaining -= size;
- postRead();
- }
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java
deleted file mode 100644
index 2e7e883a0b..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.codec;
-
-import java.nio.ByteBuffer;
-
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.qpidity.transport.RangeSet;
-
-
-/**
- * SizeEncoder
- *
- * @author Rafael H. Schloming
- */
-
-public class SizeEncoder extends AbstractEncoder implements Sizer
-{
-
- private int size;
-
- public SizeEncoder() {
- this(0);
- }
-
- public SizeEncoder(int size) {
- this.size = size;
- }
-
- protected Sizer sizer()
- {
- return Sizer.NULL;
- }
-
- public int getSize() {
- return size;
- }
-
- public void setSize(int size) {
- this.size = size;
- }
-
- public int size()
- {
- return getSize();
- }
-
- protected void doPut(byte b)
- {
- size += 1;
- }
-
- protected void doPut(ByteBuffer src)
- {
- size += src.remaining();
- }
-
- public void writeUint8(short b)
- {
- size += 1;
- }
-
- public void writeUint16(int s)
- {
- size += 2;
- }
-
- public void writeUint32(long i)
- {
- size += 4;
- }
-
- public void writeUint64(long l)
- {
- size += 8;
- }
-
- public void writeDatetime(long l)
- {
- size += 8;
- }
-
- public void writeUuid(UUID uuid)
- {
- size += 16;
- }
-
- public void writeSequenceNo(int s)
- {
- size += 4;
- }
-
- public void writeSequenceSet(RangeSet ranges)
- {
- size += 2 + 8*ranges.size();
- }
-
- //void writeByteRanges(RangeSet ranges); // XXX
-
- //void writeStr8(String s);
- //void writeStr16(String s);
-
- //void writeVbin8(byte[] bytes);
- //void writeVbin16(byte[] bytes);
- //void writeVbin32(byte[] bytes);
-
- //void writeStruct32(Struct s);
- //void writeMap(Map<String,Object> map);
- //void writeList(List<Object> list);
- //void writeArray(List<Object> array);
-
- //void writeStruct(int type, Struct s);
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java
deleted file mode 100644
index d386987d64..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.codec;
-
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
-
-
-/**
- * Sizer
- *
- */
-
-public interface Sizer extends Encoder
-{
-
- public static final Sizer NULL = new Sizer()
- {
- public void writeUint8(short b) {}
- public void writeUint16(int s) {}
- public void writeUint32(long i) {}
- public void writeUint64(long l) {}
-
- public void writeDatetime(long l) {}
- public void writeUuid(UUID uuid) {}
-
- public void writeSequenceNo(int s) {}
- public void writeSequenceSet(RangeSet ranges) {} // XXX
- public void writeByteRanges(RangeSet ranges) {} // XXX
-
- public void writeStr8(String s) {}
- public void writeStr16(String s) {}
-
- public void writeVbin8(byte[] bytes) {}
- public void writeVbin16(byte[] bytes) {}
- public void writeVbin32(byte[] bytes) {}
-
- public void writeStruct32(Struct s) {}
- public void writeMap(Map<String,Object> map) {}
- public void writeList(List<Object> list) {}
- public void writeArray(List<Object> array) {}
-
- public void writeStruct(int type, Struct s) {}
-
- public int getSize() { return 0; }
-
- public int size() { return 0; }
- };
-
- int getSize();
-
- int size();
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java
deleted file mode 100644
index 743e9f3cae..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.codec;
-
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.qpidity.transport.RangeSet;
-import org.apache.qpidity.transport.Struct;
-
-
-/**
- * Validator
- *
- */
-
-public class Validator
-{
-
- public static final void checkBit(boolean b)
- {
- // no illegal values
- }
-
- public static final void checkUint8(short s)
- {
- if (s > 0xFF || s < 0)
- {
- throw new IllegalArgumentException("" + s);
- }
- }
-
- public static final void checkUint16(int i)
- {
- if (i > 0xFFFF || i < 0)
- {
- throw new IllegalArgumentException("" + i);
- }
- }
-
- public static final void checkUint32(long l)
- {
- // XXX: we can't currently validate this because we do thinks
- // like pass in -1 for 0xFFFFFFFF
- // if (l > 0xFFFFFFFFL || l < 0)
- // {
- // throw new IllegalArgumentException("" + l);
- // }
- }
-
- public static final void checkSequenceNo(int s)
- {
- // no illegal values
- }
-
- public static final void checkUint64(long l)
- {
- // no illegal values
- }
-
- public static final void checkDatetime(long l)
- {
- // no illegal values
- }
-
- public static final void checkUuid(UUID u)
- {
- // no illegal values
- }
-
- public static final void checkStr8(String value)
- {
- if (value != null && value.length() > 255)
- {
- throw new IllegalArgumentException("" + value);
- }
- }
-
- public static final void checkStr16(String value)
- {
- if (value != null && value.length() > 0xFFFF)
- {
- throw new IllegalArgumentException("" + value);
- }
- }
-
- public static final void checkVbin8(byte[] value)
- {
- if (value != null && value.length > 255)
- {
- throw new IllegalArgumentException("" + value);
- }
- }
-
- public static final void checkVbin16(byte[] value)
- {
- if (value != null && value.length > 0xFFFF)
- {
- throw new IllegalArgumentException("" + value);
- }
- }
-
- public static final void checkByteRanges(RangeSet r)
- {
- // no illegal values
- }
-
- public static final void checkSequenceSet(RangeSet r)
- {
- // no illegal values
- }
-
- public static final void checkVbin32(byte[] value)
- {
- // no illegal values
- }
-
- public static final void checkStruct32(Struct s)
- {
- // no illegal values
- }
-
- public static final void checkArray(List<Object> array)
- {
- if (array == null)
- {
- return;
- }
-
- for (Object o : array)
- {
- checkObject(o);
- }
- }
-
- public static final void checkMap(Map<String,Object> map)
- {
- if (map == null)
- {
- return;
- }
-
- for (Map.Entry<String,Object> entry : map.entrySet())
- {
- checkStr8(entry.getKey());
- checkObject(entry.getValue());
- }
- }
-
- public static final void checkObject(Object o)
- {
- if (o != null && AbstractEncoder.resolve(o.getClass()) == null)
- {
- throw new IllegalArgumentException("cannot encode " + o.getClass());
- }
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java
deleted file mode 100644
index 3a7a550573..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.network;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import java.nio.ByteBuffer;
-
-import org.apache.qpidity.transport.codec.BBDecoder;
-import org.apache.qpidity.transport.codec.Decoder;
-import org.apache.qpidity.transport.codec.FragmentDecoder;
-
-import org.apache.qpidity.transport.ConnectionEvent;
-import org.apache.qpidity.transport.Data;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.transport.Method;
-import org.apache.qpidity.transport.ProtocolError;
-import org.apache.qpidity.transport.ProtocolEvent;
-import org.apache.qpidity.transport.ProtocolHeader;
-import org.apache.qpidity.transport.Receiver;
-import org.apache.qpidity.transport.SegmentType;
-import org.apache.qpidity.transport.Struct;
-
-
-/**
- * Assembler
- *
- */
-
-public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate
-{
-
- private final Receiver<ConnectionEvent> receiver;
- private final Map<Integer,List<ByteBuffer>> segments;
-
- public Assembler(Receiver<ConnectionEvent> receiver)
- {
- this.receiver = receiver;
- segments = new HashMap<Integer,List<ByteBuffer>>();
- }
-
- private int segmentKey(Frame frame)
- {
- // XXX: can this overflow?
- return (frame.getTrack() + 1) * frame.getChannel();
- }
-
- private List<ByteBuffer> getSegment(Frame frame)
- {
- return segments.get(segmentKey(frame));
- }
-
- private void setSegment(Frame frame, List<ByteBuffer> segment)
- {
- int key = segmentKey(frame);
- if (segments.containsKey(key))
- {
- error(new ProtocolError(Frame.L2, "segment in progress: %s",
- frame));
- }
- segments.put(segmentKey(frame), segment);
- }
-
- private void clearSegment(Frame frame)
- {
- segments.remove(segmentKey(frame));
- }
-
- private void emit(int channel, ProtocolEvent event)
- {
- receiver.received(new ConnectionEvent(channel, event));
- }
-
- private void emit(Frame frame, ProtocolEvent event)
- {
- emit(frame.getChannel(), event);
- }
-
- public void received(NetworkEvent event)
- {
- event.delegate(this);
- }
-
- public void exception(Throwable t)
- {
- this.receiver.exception(t);
- }
-
- public void closed()
- {
- this.receiver.closed();
- }
-
- public void init(ProtocolHeader header)
- {
- emit(0, header);
- }
-
- public void frame(Frame frame)
- {
- switch (frame.getType())
- {
- case BODY:
- emit(frame, new Data(frame, frame.isFirstFrame(),
- frame.isLastFrame()));
- break;
- default:
- assemble(frame);
- break;
- }
- }
-
- public void error(ProtocolError error)
- {
- emit(0, error);
- }
-
- private void assemble(Frame frame)
- {
- List<ByteBuffer> segment;
- if (frame.isFirstFrame())
- {
- segment = new ArrayList<ByteBuffer>();
- setSegment(frame, segment);
- }
- else
- {
- segment = getSegment(frame);
- }
-
- for (ByteBuffer buf : frame)
- {
- segment.add(buf);
- }
-
- if (frame.isLastFrame())
- {
- clearSegment(frame);
- emit(frame, decode(frame, frame.getType(), segment));
- }
- }
-
- private ProtocolEvent decode(Frame frame, SegmentType type, List<ByteBuffer> segment)
- {
- Decoder dec;
- if (segment.size() == 1)
- {
- dec = new BBDecoder(segment.get(0));
- }
- else
- {
- dec = new FragmentDecoder(segment.iterator());
- }
-
- switch (type)
- {
- case CONTROL:
- int controlType = dec.readUint16();
- Method control = Method.create(controlType);
- control.read(dec);
- return control;
- case COMMAND:
- int commandType = dec.readUint16();
- // read in the session header, right now we don't use it
- dec.readUint16();
- Method command = Method.create(commandType);
- command.read(dec);
- return command;
- case HEADER:
- List<Struct> structs = new ArrayList();
- while (dec.hasRemaining())
- {
- structs.add(dec.readStruct32());
- }
- return new Header(structs,frame.isLastFrame() && frame.isLastSegment());
- default:
- throw new IllegalStateException("unknown frame type: " + type);
- }
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java
deleted file mode 100644
index da9ba84ab0..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.network;
-
-import org.apache.qpidity.transport.codec.BBEncoder;
-import org.apache.qpidity.transport.codec.SizeEncoder;
-
-import org.apache.qpidity.transport.ConnectionEvent;
-import org.apache.qpidity.transport.Data;
-import org.apache.qpidity.transport.Header;
-import org.apache.qpidity.transport.Method;
-import org.apache.qpidity.transport.ProtocolDelegate;
-import org.apache.qpidity.transport.ProtocolError;
-import org.apache.qpidity.transport.ProtocolEvent;
-import org.apache.qpidity.transport.ProtocolHeader;
-import org.apache.qpidity.transport.SegmentType;
-import org.apache.qpidity.transport.Sender;
-import org.apache.qpidity.transport.Struct;
-
-import java.nio.ByteBuffer;
-import java.util.Iterator;
-
-import static org.apache.qpidity.transport.network.Frame.*;
-
-import static java.lang.Math.*;
-
-
-/**
- * Disassembler
- *
- */
-
-public class Disassembler implements Sender<ConnectionEvent>,
- ProtocolDelegate<ConnectionEvent>
-{
-
- private final Sender<NetworkEvent> sender;
- private final int maxPayload;
-
- public Disassembler(Sender<NetworkEvent> sender, int maxFrame)
- {
- if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024)
- {
- throw new IllegalArgumentException
- ("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame);
- }
- this.sender = sender;
- this.maxPayload = maxFrame - HEADER_SIZE;
-
- }
-
- public void send(ConnectionEvent event)
- {
- event.getProtocolEvent().delegate(event, this);
- }
-
- public void close()
- {
- sender.close();
- }
-
- private void fragment(byte flags, SegmentType type, ConnectionEvent event,
- ByteBuffer buf, boolean first, boolean last)
- {
- byte track = event.getProtocolEvent().getEncodedTrack() == Frame.L4 ? (byte) 1 : (byte) 0;
-
- if(!buf.hasRemaining())
- {
- //empty data
- byte nflags = flags;
- if (first)
- {
- nflags |= FIRST_FRAME;
- first = false;
- }
- nflags |= LAST_FRAME;
- Frame frame = new Frame(nflags, type, track, event.getChannel());
- // frame.addFragment(buf);
- sender.send(frame);
- }
- else
- {
- while (buf.hasRemaining())
- {
- ByteBuffer slice = buf.slice();
- slice.limit(min(maxPayload, slice.remaining()));
- buf.position(buf.position() + slice.remaining());
-
- byte newflags = flags;
- if (first)
- {
- newflags |= FIRST_FRAME;
- first = false;
- }
- if (last && !buf.hasRemaining())
- {
- newflags |= LAST_FRAME;
- }
-
- Frame frame = new Frame(newflags, type, track, event.getChannel());
- frame.addFragment(slice);
- sender.send(frame);
- }
- }
- }
-
- public void init(ConnectionEvent event, ProtocolHeader header)
- {
- sender.send(header);
- }
-
- public void control(ConnectionEvent event, Method method)
- {
- method(event, method, SegmentType.CONTROL);
- }
-
- public void command(ConnectionEvent event, Method method)
- {
- method(event, method, SegmentType.COMMAND);
- }
-
- private void method(ConnectionEvent event, Method method, SegmentType type)
- {
- SizeEncoder sizer = new SizeEncoder();
- sizer.writeUint16(method.getEncodedType());
- if (type == SegmentType.COMMAND)
- {
- sizer.writeUint16(0);
- }
- method.write(sizer);
-
- ByteBuffer buf = ByteBuffer.allocate(sizer.size());
- BBEncoder enc = new BBEncoder(buf);
- enc.writeUint16(method.getEncodedType());
- if (type == SegmentType.COMMAND)
- {
- if (method.isSync())
- {
- enc.writeUint16(0x0101);
- }
- else
- {
- enc.writeUint16(0x0100);
- }
- }
- method.write(enc);
- buf.flip();
-
- byte flags = FIRST_SEG;
-
- if (!method.hasPayload())
- {
- flags |= LAST_SEG;
- }
-
- fragment(flags, type, event, buf, true, true);
- }
-
- public void header(ConnectionEvent event, Header header)
- {
- ByteBuffer buf;
- if( header.getBuf() == null)
- {
- SizeEncoder sizer = new SizeEncoder();
- for (Struct st : header.getStructs())
- {
- sizer.writeStruct32(st);
- }
-
- buf = ByteBuffer.allocate(sizer.size());
- BBEncoder enc = new BBEncoder(buf);
- for (Struct st : header.getStructs())
- {
- enc.writeStruct32(st);
- }
- header.setBuf(buf);
- }
- else
- {
- buf = header.getBuf();
- }
- buf.flip();
- fragment((byte) 0x0, SegmentType.HEADER, event, buf, true, true);
- }
-
- public void data(ConnectionEvent event, Data data)
- {
- boolean first = data.isFirst();
- for (Iterator<ByteBuffer> it = data.getFragments().iterator();
- it.hasNext(); )
- {
- ByteBuffer buf = it.next();
- boolean last = data.isLast() && !it.hasNext();
- fragment(LAST_SEG, SegmentType.BODY, event, buf, first, last);
- first = false;
- }
- }
-
- public void error(ConnectionEvent event, ProtocolError error)
- {
- sender.send(error);
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java
deleted file mode 100644
index d1c03348b4..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.network;
-
-import java.nio.ByteBuffer;
-
-import org.apache.qpidity.transport.ProtocolError;
-import org.apache.qpidity.transport.ProtocolHeader;
-import org.apache.qpidity.transport.Receiver;
-import org.apache.qpidity.transport.SegmentType;
-
-import static org.apache.qpidity.transport.util.Functions.*;
-
-import static org.apache.qpidity.transport.network.InputHandler.State.*;
-
-
-/**
- * InputHandler
- *
- * @author Rafael H. Schloming
- */
-
-public class InputHandler implements Receiver<ByteBuffer>
-{
-
- public enum State
- {
- PROTO_HDR,
- PROTO_HDR_M,
- PROTO_HDR_Q,
- PROTO_HDR_P,
- PROTO_HDR_CLASS,
- PROTO_HDR_INSTANCE,
- PROTO_HDR_MAJOR,
- PROTO_HDR_MINOR,
- FRAME_HDR,
- FRAME_HDR_TYPE,
- FRAME_HDR_SIZE1,
- FRAME_HDR_SIZE2,
- FRAME_HDR_RSVD1,
- FRAME_HDR_TRACK,
- FRAME_HDR_CH1,
- FRAME_HDR_CH2,
- FRAME_HDR_RSVD2,
- FRAME_HDR_RSVD3,
- FRAME_HDR_RSVD4,
- FRAME_HDR_RSVD5,
- FRAME_FRAGMENT,
- ERROR;
- }
-
- private final Receiver<NetworkEvent> receiver;
- private State state;
-
- private byte instance;
- private byte major;
- private byte minor;
-
- private byte flags;
- private SegmentType type;
- private byte track;
- private int channel;
- private int size;
- private Frame frame;
-
- public InputHandler(Receiver<NetworkEvent> receiver, State state)
- {
- this.receiver = receiver;
- this.state = state;
- }
-
- public InputHandler(Receiver<NetworkEvent> receiver)
- {
- this(receiver, PROTO_HDR);
- }
-
- private void init()
- {
- receiver.received(new ProtocolHeader(instance, major, minor));
- }
-
- private void frame()
- {
- assert size == frame.getSize();
- receiver.received(frame);
- frame = null;
- }
-
- private void error(String fmt, Object ... args)
- {
- receiver.received(new ProtocolError(Frame.L1, fmt, args));
- }
-
- public void received(ByteBuffer buf)
- {
- while (buf.hasRemaining())
- {
- state = next(buf);
- }
- }
-
- private State next(ByteBuffer buf)
- {
- switch (state) {
- case PROTO_HDR:
- return expect(buf, 'A', PROTO_HDR_M);
- case PROTO_HDR_M:
- return expect(buf, 'M', PROTO_HDR_Q);
- case PROTO_HDR_Q:
- return expect(buf, 'Q', PROTO_HDR_P);
- case PROTO_HDR_P:
- return expect(buf, 'P', PROTO_HDR_CLASS);
- case PROTO_HDR_CLASS:
- return expect(buf, 1, PROTO_HDR_INSTANCE);
- case PROTO_HDR_INSTANCE:
- instance = buf.get();
- return PROTO_HDR_MAJOR;
- case PROTO_HDR_MAJOR:
- major = buf.get();
- return PROTO_HDR_MINOR;
- case PROTO_HDR_MINOR:
- minor = buf.get();
- init();
- return FRAME_HDR;
- case FRAME_HDR:
- flags = buf.get();
- return FRAME_HDR_TYPE;
- case FRAME_HDR_TYPE:
- type = SegmentType.get(buf.get());
- return FRAME_HDR_SIZE1;
- case FRAME_HDR_SIZE1:
- size = (0xFF & buf.get()) << 8;
- return FRAME_HDR_SIZE2;
- case FRAME_HDR_SIZE2:
- size += 0xFF & buf.get();
- size -= 12;
- if (size < 0 || size > (64*1024 - 12))
- {
- error("bad frame size: %d", size);
- return ERROR;
- }
- else
- {
- return FRAME_HDR_RSVD1;
- }
- case FRAME_HDR_RSVD1:
- return expect(buf, 0, FRAME_HDR_TRACK);
- case FRAME_HDR_TRACK:
- byte b = buf.get();
- if ((b & 0xF0) != 0) {
- error("non-zero reserved bits in upper nibble of " +
- "frame header byte 5: '%x'", b);
- return ERROR;
- } else {
- track = (byte) (b & 0xF);
- return FRAME_HDR_CH1;
- }
- case FRAME_HDR_CH1:
- channel = (0xFF & buf.get()) << 8;
- return FRAME_HDR_CH2;
- case FRAME_HDR_CH2:
- channel += 0xFF & buf.get();
- return FRAME_HDR_RSVD2;
- case FRAME_HDR_RSVD2:
- return expect(buf, 0, FRAME_HDR_RSVD3);
- case FRAME_HDR_RSVD3:
- return expect(buf, 0, FRAME_HDR_RSVD4);
- case FRAME_HDR_RSVD4:
- return expect(buf, 0, FRAME_HDR_RSVD5);
- case FRAME_HDR_RSVD5:
- if (!expect(buf, 0))
- {
- return ERROR;
- }
-
- frame = new Frame(flags, type, track, channel);
- if (size > buf.remaining()) {
- frame.addFragment(buf.slice());
- buf.position(buf.limit());
- return FRAME_FRAGMENT;
- } else {
- ByteBuffer payload = buf.slice();
- payload.limit(size);
- buf.position(buf.position() + size);
- frame.addFragment(payload);
- frame();
- return FRAME_HDR;
- }
- case FRAME_FRAGMENT:
- int delta = size - frame.getSize();
- if (delta > buf.remaining()) {
- frame.addFragment(buf.slice());
- buf.position(buf.limit());
- return FRAME_FRAGMENT;
- } else {
- ByteBuffer fragment = buf.slice();
- fragment.limit(delta);
- buf.position(buf.position() + delta);
- frame.addFragment(fragment);
- frame();
- return FRAME_HDR;
- }
- default:
- throw new IllegalStateException();
- }
- }
-
- private State expect(ByteBuffer buf, int expected, State next)
- {
- return expect(buf, (byte) expected, next);
- }
-
- private State expect(ByteBuffer buf, char expected, State next)
- {
- return expect(buf, (byte) expected, next);
- }
-
- private State expect(ByteBuffer buf, byte expected, State next)
- {
- if (expect(buf, expected))
- {
- return next;
- }
- else
- {
- return ERROR;
- }
- }
-
- private boolean expect(ByteBuffer buf, int expected)
- {
- return expect(buf, (byte) expected);
- }
-
- private boolean expect(ByteBuffer buf, byte expected)
- {
- byte b = buf.get();
- if (b == expected)
- {
- return true;
- }
- else
- {
- error("expecting '%x', got '%x'", expected, b);
- return false;
- }
- }
-
- public void exception(Throwable t)
- {
- receiver.exception(t);
- }
-
- public void closed()
- {
- receiver.closed();
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java
deleted file mode 100644
index b749332fa3..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpidity.transport.network;
-
-import java.nio.ByteBuffer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.qpidity.transport.Constant;
-import org.apache.qpidity.transport.ProtocolError;
-import org.apache.qpidity.transport.ProtocolHeader;
-import org.apache.qpidity.transport.Sender;
-
-import static org.apache.qpidity.transport.network.Frame.*;
-
-
-/**
- * OutputHandler
- *
- */
-
-public class OutputHandler implements Sender<NetworkEvent>, NetworkDelegate
-{
-
- private Sender<ByteBuffer> sender;
- private Object lock = new Object();
- private int bytes = 0;
- private List<Frame> frames = new ArrayList<Frame>();
-
- public OutputHandler(Sender<ByteBuffer> sender)
- {
- this.sender = sender;
- }
-
- public void send(NetworkEvent event)
- {
- event.delegate(this);
- }
-
- public void close()
- {
- synchronized (lock)
- {
- sender.close();
- }
- }
-
- public void init(ProtocolHeader header)
- {
- synchronized (lock)
- {
- sender.send(header.toByteBuffer());
- }
- }
-
- public void frame(Frame frame)
- {
- synchronized (lock)
- {
- frames.add(frame);
- bytes += HEADER_SIZE + frame.getSize();
-
- if (frame.isLastFrame() && frame.isLastSegment() || bytes > 64*1024)
- {
- ByteBuffer buf = ByteBuffer.allocate(bytes);
- for (Frame f : frames)
- {
- buf.put(f.getFlags());
- buf.put((byte) f.getType().getValue());
- buf.putShort((short) (f.getSize() + HEADER_SIZE));
- // RESERVED
- buf.put(RESERVED);
- buf.put(f.getTrack());
- buf.putShort((short) f.getChannel());
- // RESERVED
- buf.putInt(0);
- for(ByteBuffer frg : f)
- {
- buf.put(frg);
- }
- }
- buf.flip();
-
- frames.clear();
- bytes = 0;
-
- sender.send(buf);
- }
- }
- }
-
- public void error(ProtocolError error)
- {
- throw new IllegalStateException("XXX");
- }
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java
deleted file mode 100644
index 568526d9db..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.qpidity.transport.network.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.qpidity.transport.Connection;
-import org.apache.qpidity.transport.ConnectionDelegate;
-import org.apache.qpidity.transport.Receiver;
-import org.apache.qpidity.transport.network.Assembler;
-import org.apache.qpidity.transport.network.Disassembler;
-import org.apache.qpidity.transport.network.InputHandler;
-import org.apache.qpidity.transport.network.OutputHandler;
-import org.apache.qpidity.transport.util.Logger;
-
-/**
- * This class provides a synchronous IO implementation using
- * the java.io classes. The IoHandler runs in its own thread.
- * The following params are configurable via JVM arguments
- * TCP_NO_DELAY - amqj.tcpNoDelay
- * SO_RCVBUF - amqj.receiveBufferSize
- * SO_SNDBUF - amqj.sendBufferSize
- */
-public class IoHandler implements Runnable
-{
- private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024;
-
- private Receiver<ByteBuffer> _receiver;
- private Socket _socket;
- private byte[] _readBuf;
- private static AtomicInteger _count = new AtomicInteger();
- private int _readBufferSize;
- private int _writeBufferSize;
-
- private static final Logger log = Logger.get(IoHandler.class);
-
- private IoHandler()
- {
- _readBufferSize = Integer.getInteger("amqj.receiveBufferSize",DEFAULT_READ_WRITE_BUFFER_SIZE);
- _writeBufferSize = Integer.getInteger("amqj.sendBufferSize",DEFAULT_READ_WRITE_BUFFER_SIZE);
- }
-
- public static final Connection connect(String host, int port,
- ConnectionDelegate delegate)
- {
- IoHandler handler = new IoHandler();
- return handler.connectInternal(host,port,delegate);
- }
-
- private Connection connectInternal(String host, int port,
- ConnectionDelegate delegate)
- {
- try
- {
- InetAddress address = InetAddress.getByName(host);
- _socket = new Socket();
- _socket.setReuseAddress(true);
- _socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay"));
-
- log.debug("default-SO_RCVBUF : " + _socket.getReceiveBufferSize());
- log.debug("default-SO_SNDBUF : " + _socket.getSendBufferSize());
-
- _socket.setSendBufferSize(_writeBufferSize);
- _socket.setReceiveBufferSize(_readBufferSize);
-
- log.debug("new-SO_RCVBUF : " + _socket.getReceiveBufferSize());
- log.debug("new-SO_SNDBUF : " + _socket.getSendBufferSize());
-
- if (address != null)
- {
- _socket.connect(new InetSocketAddress(address, port));
- }
- while (!_socket.isConnected())
- {
-
- }
-
- }
- catch (SocketException e)
- {
- throw new RuntimeException("Error connecting to broker",e);
- }
- catch (IOException e)
- {
- throw new RuntimeException("Error connecting to broker",e);
- }
-
- IoSender sender = new IoSender(_socket);
- Connection con = new Connection
- (new Disassembler(new OutputHandler(sender), 64*1024 - 1),
- delegate);
-
- con.setConnectionId(_count.incrementAndGet());
- _receiver = new InputHandler(new Assembler(con), InputHandler.State.PROTO_HDR);
-
- Thread t = new Thread(this);
- t.setName("IO Handler Thread-" + _count.get());
- t.start();
-
- return con;
- }
-
- public void run()
- {
- // I set the read_buffer size simillar to SO_RCVBUF
- // Haven't tested with a lower value to see its better or worse
- _readBuf = new byte[_readBufferSize];
- try
- {
- InputStream in = _socket.getInputStream();
- int read = 0;
- while(_socket.isConnected())
- {
- try
- {
- read = in.read(_readBuf);
- if (read > 0)
- {
- ByteBuffer b = ByteBuffer.allocate(read);
- b.put(_readBuf,0,read);
- b.flip();
- _receiver.received(b);
- }
- }
- catch(Exception e)
- {
- throw new RuntimeException("Error reading from socket input stream",e);
- }
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("Error getting input stream from the socket",e);
- }
- finally
- {
- try
- {
- _socket.close();
- }
- catch(Exception e)
- {
- log.error(e,"Error closing socket");
- }
- }
- }
-
- /**
- * Will experiment in a future version with batching
- */
- public static void startBatchingFrames(int connectionId)
- {
-
- }
-
-
-}
diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java
deleted file mode 100644
index 1adde531a6..0000000000
--- a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.qpidity.transport.network.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import org.apache.qpidity.transport.Sender;
-
-public class IoSender implements Sender<java.nio.ByteBuffer>
-{
- private final Object lock = new Object();
- private Socket _socket;
- private OutputStream _outStream;
-
- public IoSender(Socket socket)
- {
- this._socket = socket;
- try
- {
- _outStream = _socket.getOutputStream();
- }
- catch(IOException e)
- {
- throw new RuntimeException("Error getting output stream for socket",e);
- }
- }
-
- /*
- * Currently I don't implement any in memory buffering
- * and just write straight to the wire.
- * I want to experiment with buffering and see if I can
- * get more performance, all though latency will suffer
- * a bit.
- */
- public void send(java.nio.ByteBuffer buf)
- {
- write(buf);
- }
-
- /* The extra copying sucks.
- * If I know for sure that the buf is backed
- * by an array then I could do buf.array()
- */
- private void write(java.nio.ByteBuffer buf)
- {
- byte[] array = new byte[buf.remaining()];
- buf.get(array);
- if( _socket.isConnected())
- {
- synchronized (lock)
- {
- try
- {
- _outStream.write(array);
- }
- catch(Exception e)
- {
- e.fillInStackTrace();
- throw new RuntimeException("Error trying to write to the socket",e);
- }
- }
- }
- else
- {
- throw new RuntimeException("Trying to write on a closed socket");
- }
- }
-
- /*
- * Haven't used this, but the intention is
- * to experiment with it in the future.
- * Also need to make sure the buffer size
- * is configurable
- */
- public void setStartBatching()
- {
- }
-
- public void close()
- {
- synchronized (lock)
- {
- try
- {
- _socket.close();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- }
-}
diff --git a/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java
index 1a83786e12..b9ca210483 100644
--- a/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java
+++ b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java
@@ -18,14 +18,16 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import org.apache.mina.util.AvailablePortFinder;
import org.apache.qpid.util.concurrent.Condition;
-import org.apache.qpidity.transport.network.mina.MinaHandler;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.transport.network.ConnectionBinding;
+import org.apache.qpid.transport.network.io.IoAcceptor;
+import org.apache.qpid.transport.network.io.IoTransport;
+import org.apache.qpid.transport.util.Logger;
import junit.framework.TestCase;
@@ -62,12 +64,14 @@ public class ConnectionTest extends TestCase
public void closed() {}
};
- MinaHandler.accept("localhost", port, server);
+ IoAcceptor ioa = new IoAcceptor
+ ("localhost", port, new ConnectionBinding(server));
+ ioa.start();
}
private Connection connect(final Condition closed)
{
- Connection conn = MinaHandler.connect("localhost", port, new ConnectionDelegate()
+ Connection conn = IoTransport.connect("localhost", port, new ConnectionDelegate()
{
public SessionDelegate getSessionDelegate()
{
@@ -86,7 +90,7 @@ public class ConnectionTest extends TestCase
}
});
- conn.send(new ConnectionEvent(0, new ProtocolHeader(1, 0, 10)));
+ conn.send(new ProtocolHeader(1, 0, 10));
return conn;
}
diff --git a/java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java
index 474d47d8d7..ad45d00e46 100644
--- a/java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java
+++ b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpidity.transport;
+package org.apache.qpid.transport;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/java/cpp.async.testprofile b/java/cpp.async.testprofile
index 5e9b14ea9f..c7554165f0 100644
--- a/java/cpp.async.testprofile
+++ b/java/cpp.async.testprofile
@@ -1,18 +1,3 @@
broker.version=0-10
broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --load-module ${project.root}/../../cppStore/cpp/lib/.libs/libbdbstore.so --auth no
-broker.clean=${project.root}/clean-dir ${build.data}
-broker.ready=Listening on TCP port
-java.naming.provider.url=${project.root}/test-provider.properties
-max_prefetch=1000
-test.excludes=true
test.excludesfile=${project.root}/010ExcludeList-store
-log=info
-amqj.logging.level=$log
-root.logging.level=$log
-log4j.configuration=file://${project.root}/log4j-test.xml
-test.fork=no
-test.mem=512M
-test=*Test
-haltonfailure=no
-haltonerror=no
-exclude.modules=none
diff --git a/java/cpp.noprefetch.testprofile b/java/cpp.noprefetch.testprofile
new file mode 100644
index 0000000000..1e4f62dd8c
--- /dev/null
+++ b/java/cpp.noprefetch.testprofile
@@ -0,0 +1,4 @@
+broker.version=0-10
+broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --load-module ${project.root}/../../cppStore/cpp/lib/.libs/libbdbstore.so --auth no
+test.excludesfile=${project.root}/010ExcludeList-noPrefetch
+max_prefetch=0 \ No newline at end of file
diff --git a/java/cpp.sync.testprofile b/java/cpp.sync.testprofile
deleted file mode 100644
index cb52937cd1..0000000000
--- a/java/cpp.sync.testprofile
+++ /dev/null
@@ -1,18 +0,0 @@
-broker.version=0-10
-broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --load-module ${project.root}/../../cppStore/cpp/lib/.libs/libbdbstore.so --store-async no --auth no
-broker.clean=${project.root}/clean-dir ${build.data}
-broker.ready=Listening on TCP port
-java.naming.provider.url=${project.root}/test-provider.properties
-test.excludes=true
-max_prefetch=1000
-test.excludesfile=${project.root}/010ExcludeList-store
-log=info
-amqj.logging.level=$log
-root.logging.level=$log
-log4j.configuration=file://${project.root}/log4j-test.xml
-test.fork=no
-test.mem=512M
-test=*Test
-haltonfailure=no
-haltonerror=no
-exclude.modules=none
diff --git a/java/cpp.testprofile b/java/cpp.testprofile
index 6db245b007..68ac8b8be8 100644
--- a/java/cpp.testprofile
+++ b/java/cpp.testprofile
@@ -1,18 +1,3 @@
broker.version=0-10
broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --auth no
-broker.clean=${project.root}/clean-dir ${build.data}
-broker.ready=Listening on TCP port
-java.naming.provider.url=${project.root}/test-provider.properties
-max_prefetch=1000
-test.excludes=true
test.excludesfile=${project.root}/010ExcludeList
-log=info
-amqj.logging.level=$log
-root.logging.level=$log
-log4j.configuration=file://${project.root}/log4j-test.xml
-test.fork=no
-test.mem=512M
-test=*Test
-haltonfailure=no
-haltonerror=no
-exclude.modules=none
diff --git a/java/default-longrunning.testprofile b/java/default-longrunning.testprofile
new file mode 100644
index 0000000000..155e78ad0a
--- /dev/null
+++ b/java/default-longrunning.testprofile
@@ -0,0 +1 @@
+test.includesfile=${project.root}/08LongRunningList
diff --git a/java/default.testprofile b/java/default.testprofile
index 4f749b84a7..7354cbda48 100644
--- a/java/default.testprofile
+++ b/java/default.testprofile
@@ -1,14 +1,20 @@
broker.version=0-8
broker=vm
broker.clean=${project.root}/clean-dir ${build.data}
+broker.ready=Listening on TCP port
+
java.naming.provider.url=${project.root}/test-provider.properties
-test.excludes=true
-test.excludesfile=${project.root}/08ExcludeList
-log=info
max_prefetch=1000
-amqj.logging.level=$log
-root.logging.level=$log
+
+log=debug
+amqj.logging.level=${log}
+amqj.protocol.logging.level=${log}
+root.logging.level=${log}
log4j.configuration=file:///${project.root}/log4j-test.xml
+log4j.debug=false
+
+test.excludes=true
+test.excludesfile=${project.root}/08ExcludeList
test.fork=no
test.mem=512M
test=*Test
diff --git a/java/integrationtests/bin/interoptests.py b/java/integrationtests/bin/interoptests.py
new file mode 100755
index 0000000000..f5a50fc1eb
--- /dev/null
+++ b/java/integrationtests/bin/interoptests.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import glob, os, subprocess
+from subprocess import Popen
+from optparse import OptionParser
+
+interop_cases = ["InteropTestCase1DummyRun", "InteropTestCase2BasicP2P", "InteropTestCase3BasicPubSub", "InteropTestCase4P2PMessageSize", "InteropTestCase5PubSubMessageSize"]
+
+interop_command = "java -cp %s org.apache.qpid.test.framework.distributedtesting.Coordinator --xml -e interop -o . -n interop org.apache.qpid.interop.testcases.%s"
+
+# TODO: read this from the ant properties file
+clientlibs = ["qpid-integrationtests-incubating-M3.jar",
+ "qpid-junit-toolkit-incubating-M3.jar",
+ "junit-3.8.1.jar",
+ "qpid-systests-incubating-M3.jar",
+ "qpid-junit-toolkit-incubating-M3.jar",
+ "geronimo-jms_1.1_spec-1.0.jar",
+ "log4j-1.2.12.jar"]
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-t", "--testlib", dest="testlib", action="store",
+ type="string",
+ help="The directory containing the test classes to run")
+ parser.add_option("-b", "--brokers", dest="brokers", action="store",
+ type="string",
+ help="The directory containing the unpacked brokers to test")
+ parser.add_option("-j", "--java", dest="java", action="store",
+ type="string",
+ help="The directory containing the java client to test")
+ parser.add_option("-d", "--dotnet", dest="dotnet", action="store",
+ type="string",
+ help="The directory containing the .Net client to test")
+ parser.add_option("-c", "--cpp", dest="cpp", action="store",
+ type="string",
+ help="The directory containing the C++ client to test")
+ (options, args) = parser.parse_args()
+
+ # check available brokers
+ if (options.brokers == None or
+ not os.path.exists(options.brokers) or
+ not os.path.isdir(options.brokers)):
+ parser.error("Broker directory must be specified and must exist")
+
+ # check available clients
+ if (options.java == None or
+ not os.path.exists(options.java) or
+ not os.path.isdir(options.java)):
+ parser.error("Java client directory must be specified and must exist")
+
+ # check available tests
+ if (options.testlib == None or
+ not os.path.exists(options.testlib) or
+ not os.path.isdir(options.testlib)):
+ parser.error("Test directory must be specified and must exist")
+
+ # check dotnet test client
+ if (options.dotnet == None or
+ not os.path.exists(options.dotnet) or
+ not os.path.exists(options.dotnet+"/TestClient.exe")):
+ parser.error(".Net test directory must be specified and must contain TestClient.exe")
+
+ # check cpp test client
+ if (options.cpp == None or
+ not os.path.exists(options.cpp) or
+ not os.path.exists(options.cpp+"/src/tests/interop_runner")):
+ parser.error("C++ test directory must be specified and must contain test client")
+
+ # Get list of available broker and client versions
+ brokers = glob.glob(options.brokers+"/qpid-[0-9].[0-9].[0-9].[0-9]")
+ java_clients = glob.glob(options.java+"/qpid-[0-9].[0-9].[0-9].[0-9]*")
+
+ if (not len(brokers) > 0):
+ parser.error("Broker directory did not contain any brokers!")
+
+ if (not len(java_clients) > 0):
+ parser.error("Broker directory did not contain any brokers!")
+
+ for broker in brokers:
+ for client in java_clients:
+ test(options.testlib, broker, client, options.dotnet,
+ options.cpp)
+
+def start_dotnet(dotnetpath):
+ return Popen(["%s/TestClient.exe" % os.path.abspath(dotnetpath),
+ "-bamqp://guest:guest@clientid/?brokerlist=\'tcp://localhost:5672\'"],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+def start_java(javapath):
+ # Setup classpath
+ classpath = ""
+ for lib in clientlibs:
+ classpath = classpath + testlibdir+"/"+lib+";"
+
+ classpath = classpath + javapath+"/lib/qpid-incubating.jar"
+
+ # Add qpid common since the tests need that, classpath hatefulness
+ classpath = classpath + ";"+testlibdir+"/qpid-common-incubating-M3.jar"
+
+ return Popen(["java", "-cp","\""+classpath+"\"",
+ "org.apache.qpid.test.framework.distributedtesting.TestClient"],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+def start_cpp(cpppath):
+ return Popen([cpppath+"tests/interop_runner"],
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+def run_tests():
+ for testcase in interop_cases:
+ cmd = " ".join(["java", "-cp","\""+classpath+"\"", "org.apache.qpid.test.framework.distributedtesting.Coordinator",
+ "--xml", "-e", "interop", "-o", ".", "-n", "interop", ("org.apache.qpid.interop.testcases.%s" % testcase)])
+ fd = os.popen(cmd, "r")
+ output = fd.read()
+ fd.close()
+
+def test(testlibdir, brokerpath, javapath, dotnetpath, cpppath):
+ print ("Testing broker in %s\nclient in %s" % (brokerpath, javapath))
+ print ("Logging too %s" % ("/tmp/qpid-interop-tests/%s-%s" %
+ (os.path.basename(brokerpath), os.path.basename(javapath))))
+ os.environ["QPID_HOME"] = brokerpath
+ os.environ["QPID_WORK"] = ("/tmp/qpid-interop-tests/%s-%s" %
+ (os.path.basename(brokerpath), os.path.basename(javapath)))
+
+ brokerp, javacp, dotnetp, cppp, coordinatorp = (None, None, None, None, None)
+
+ try:
+ # Start broker
+ brokerp = Popen(brokerpath+"/bin/qpid-server",
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ print ("Started broker, pid %s" % brokerp.pid)
+
+ cppp = start_cpp(cpppath)
+ print ("Started C++ client, pid %s" % cppp.pid)
+
+ dotnetp = start_dotnet(dotnetpath)
+ print ("Started .Net client, pid %s" % dotnetp.pid)
+
+ javacp = start_java(javapath)
+ print ("Started client, pid %s" % javacp.pid)
+
+ run_tests()
+
+ finally:
+ # Shutdown broker and clients
+ if javacp != None:
+ os.kill(javacp.pid, 9)
+ if dotnetp != None:
+ os.kill(dotnetp.pid, 9)
+ if coordinatorp != None:
+ os.kill(coordinatorp.pid, 9)
+ if brokerp != None:
+ os.kill(brokerp.pid, 9)
+
+ # Start coordinator
+
+
+if __name__ == "__main__":
+ main()
diff --git a/java/java.testprofile b/java/java.testprofile
new file mode 100644
index 0000000000..cef0a10661
--- /dev/null
+++ b/java/java.testprofile
@@ -0,0 +1,5 @@
+broker=${project.root}/build/bin/qpid-server
+broker.clean=${project.root}/clean-dir ${build.data}
+broker.ready=Qpid Broker Ready
+
+test.excludesfile=${project.root}/08ExcludeList-nonvm
diff --git a/java/junit-toolkit/pom.xml b/java/junit-toolkit/pom.xml
index 2b57c26a13..c5f0d75a74 100644
--- a/java/junit-toolkit/pom.xml
+++ b/java/junit-toolkit/pom.xml
@@ -52,6 +52,18 @@
<version>1.2.12</version>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+
</dependencies>
</dependencyManagement>
@@ -65,6 +77,19 @@
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+
</dependencies>
<build>
diff --git a/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java b/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
index 605c35feed..3cf8543656 100644
--- a/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
+++ b/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
@@ -20,7 +20,8 @@
*/
package org.apache.qpid.junit.concurrency;
-import org.apache.log4j.Logger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
@@ -68,7 +69,7 @@ import java.util.concurrent.ThreadFactory;
public class ThreadTestCoordinator
{
/** Used for logging. */
- private static final Logger log = Logger.getLogger(ThreadTestCoordinator.class);
+ private static final Logger log = LoggerFactory.getLogger(ThreadTestCoordinator.class);
/** Keeps track of the test threads by their ids. */
private TestRunnable[] testThreads; // = new TestRunnable[2];
diff --git a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java b/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
index 1c1c146361..e99fcce752 100644
--- a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
+++ b/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
@@ -95,30 +95,36 @@ public class DurationTestDecorator extends WrappedSuiteTestDecorator implements
{
log.debug("public void run(TestResult testResult): called");
- // Cast the test result to expose it as a TKTestResult if the test is running under the TKTestRunner.
- TKTestResult tkTestResult = null;
+// Removing the durationTimer as this addition prevents this TestDecorator being wrapped with a Scaled Test Decorator.
+ // This change will cause the tests to run for at least the specified duration
+ // If we need the test to stop much closer to the specified duration then we need to
+ // ensure that the solution doesn't prevent this Decorator being wrapped with other Decorators.
+
+// // Cast the test result to expose it as a TKTestResult if the test is running under the TKTestRunner.
+// TKTestResult tkTestResult = null;
+//
+// if (testResult instanceof TKTestResult)
+// {
+// tkTestResult = (TKTestResult) testResult;
+// }
+//
+// // If running under the TKTestRunner, set up a timer to notify the test framework when the test reaches its
+// // completion time.
+// Timer durationTimer = null;
+//
+// if (tkTestResult != null)
+// {
+// log.debug("Creating duration timer.");
+//
+// durationTimer = new Timer();
+// durationTimer.schedule(new DurationTimerTask((TKTestResult) testResult), duration);
+// }
- if (testResult instanceof TKTestResult)
- {
- tkTestResult = (TKTestResult) testResult;
- }
// Work out when the test should end.
long now = System.nanoTime();
long end = (duration * 1000000) + now;
- // If running under the TKTestRunner, set up a timer to notify the test framework when the test reaches its
- // completion time.
- Timer durationTimer = null;
-
- if (tkTestResult != null)
- {
- log.debug("Creating duration timer.");
-
- durationTimer = new Timer();
- durationTimer.schedule(new DurationTimerTask((TKTestResult) testResult), duration);
- }
-
// Run the test until the duration times out or the shutdown flag is set. The test method may not exit until
// interrupted in some cases, in which case the timer will do the interrupting.
while ((now < end) && !shutdown)
@@ -128,13 +134,13 @@ public class DurationTestDecorator extends WrappedSuiteTestDecorator implements
now = System.nanoTime();
}
- // Clean up any timer that was used.
- if (durationTimer != null)
- {
- log.debug("Cancelling duration timer.");
-
- durationTimer.cancel();
- }
+// // Clean up any timer that was used.
+// if (durationTimer != null)
+// {
+// log.debug("Cancelling duration timer.");
+//
+// durationTimer.cancel();
+// }
}
/**
@@ -157,43 +163,43 @@ public class DurationTestDecorator extends WrappedSuiteTestDecorator implements
});
}
- /**
- * DurationTimerTask is a timer task that is configured, upon expiry of its timer, to invoke
- * {@link TKTestResult#shutdownNow()}, for the test result object on which it is set. It also sets
- * the {@link DurationTestDecorator#shutdown} flag to indicate that no new tests should be run.
- *
- * <p/>The test loop implemented by DurationTestDecorator checks that the duration has not expired, on each
- * test case that it runs. However, it is possible to write test cases that never return until explicitly
- * interrupted by the test framework. This timer task exists to notify the test framework
- */
- private class DurationTimerTask extends TimerTask
- {
- /** Used for debugging purposes. */
- private final Logger log = Logger.getLogger(DurationTimerTask.class);
-
- /** Holds the test result for the test to which a duration limit is being applied. */
- TKTestResult testResult;
-
- /**
- * Creates a duration limit timer which will notify the specified test result when the duration has
- * expired.
- *
- * @param testResult The test result to notify upon expiry of the test duration.
- */
- public DurationTimerTask(TKTestResult testResult)
- {
- this.testResult = testResult;
- }
-
- /**
- * The action to be performed by this timer task.
- */
- public void run()
- {
- log.debug("public void run(): called");
-
- shutdown = true;
- testResult.shutdownNow();
- }
- }
+// /**
+// * DurationTimerTask is a timer task that is configured, upon expiry of its timer, to invoke
+// * {@link TKTestResult#shutdownNow()}, for the test result object on which it is set. It also sets
+// * the {@link DurationTestDecorator#shutdown} flag to indicate that no new tests should be run.
+// *
+// * <p/>The test loop implemented by DurationTestDecorator checks that the duration has not expired, on each
+// * test case that it runs. However, it is possible to write test cases that never return until explicitly
+// * interrupted by the test framework. This timer task exists to notify the test framework
+// */
+// private class DurationTimerTask extends TimerTask
+// {
+// /** Used for debugging purposes. */
+// private final Logger log = Logger.getLogger(DurationTimerTask.class);
+//
+// /** Holds the test result for the test to which a duration limit is being applied. */
+// TKTestResult testResult;
+//
+// /**
+// * Creates a duration limit timer which will notify the specified test result when the duration has
+// * expired.
+// *
+// * @param testResult The test result to notify upon expiry of the test duration.
+// */
+// public DurationTimerTask(TKTestResult testResult)
+// {
+// this.testResult = testResult;
+// }
+//
+// /**
+// * The action to be performed by this timer task.
+// */
+// public void run()
+// {
+// log.debug("public void run(): called");
+//
+// shutdown = true;
+// testResult.shutdownNow();
+// }
+// }
}
diff --git a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java b/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
index edd79b3697..c68405bd06 100644
--- a/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
+++ b/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
@@ -86,7 +86,7 @@ public class TestRunnerImprovedErrorHandling extends TestRunner
*
* @throws Exception Any exceptions falling through the tests are wrapped in Exception and rethrown.
*/
- protected TestResult start(String[] args) throws Exception
+ public TestResult start(String[] args) throws Exception
{
String testCase = "";
boolean wait = false;
diff --git a/java/log4j-test.xml b/java/log4j-test.xml
index c5fa8abe47..c242286b70 100644
--- a/java/log4j-test.xml
+++ b/java/log4j-test.xml
@@ -30,16 +30,24 @@
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
+ <param name="ConversionPattern" value="%t %d %p [%c{4}] %m%n"/>
</layout>
</appender>
<logger name="org.apache.qpid">
- <level value="debug"/>
+ <level value="${amqj.logging.level}"/>
+ </logger>
+
+ <logger name="qpid.protocol">
+ <level value="${amqj.protocol.logging.level}"/>
+ </logger>
+
+ <logger name="org.apache.qpid.test.utils.QpidTestCase">
+ <level value="ALL"/>
</logger>
<root>
- <level value="debug"/>
+ <level value="${root.logging.level}"/>
<appender-ref ref="console" />
</root>
</log4j:configuration>
diff --git a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java b/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
index 56eadbb3b2..fb616e2b59 100644
--- a/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
+++ b/java/management/eclipse-plugin/src/test/java/org/apache/qpid/management/ui/ManagementConsoleTest.java
@@ -23,10 +23,11 @@ package org.apache.qpid.management.ui;
import junit.framework.TestCase;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.exchange.DestNameExchange;
+import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.management.AMQManagedObject;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.AMQQueueMBean;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
@@ -62,7 +63,8 @@ public class ManagementConsoleTest extends TestCase
{
// If this test fails due to changes in the broker code,
// then the constants in the Constants.java shoule be updated accordingly
- AMQQueue queue = new AMQQueue(new AMQShortString("testQueueForManagement"), false, null, false, _virtualHost);
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueueForManagement"), false, null, false, _virtualHost,
+ null);
AMQManagedObject mbean = new AMQQueueMBean(queue);
MBeanInfo mbeanInfo = mbean.getMBeanInfo();
@@ -82,7 +84,7 @@ public class ManagementConsoleTest extends TestCase
{
// If this test fails due to changes in the broker code,
// then the constants in the Constants.java shoule be updated accordingly
- DestNameExchange exchange = new DestNameExchange();
+ DirectExchange exchange = new DirectExchange();
exchange.initialise(_virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true);
AMQManagedObject mbean = (AMQManagedObject)exchange.getManagedObject();
MBeanInfo mbeanInfo = mbean.getMBeanInfo();
diff --git a/java/module.xml b/java/module.xml
index 42385e3f53..50b68ee633 100644
--- a/java/module.xml
+++ b/java/module.xml
@@ -26,7 +26,7 @@
<globmapper from="${project.root}${file.separator}*" to="*"/>
</map>
- <echo message="Running ant for module : ${module}"/>
+ <echo message="Running ant for module : ${module}" level="info"/>
<property file="${project.root}/build.deps"/>
@@ -142,9 +142,13 @@
<target name="precompile"/>
<target name="compile" depends="prepare,precompile" description="compile sources">
- <javac source="${java.source}" target="${java.target}"
+
+ <echo message="Targeting : ${java.target}" level="info"/>
+
+ <javac source="${java.source}" target="${java.target}"
destdir="${module.classes}" debug="on"
deprecation="${javac.deprecation}">
+ <compilerarg line="${javac.compiler.args}"/>
<src refid="module.src.path"/>
<classpath refid="module.class.path"/>
</javac>
@@ -189,6 +193,7 @@
<property file="${project.root}/${config}"/>
+ <property file="${project.root}/default.testprofile"/>
<condition property="dontruntest" value="dontruntest" else="runtest">
<contains substring="${module.name}" string="${exclude.modules}" />
@@ -199,11 +204,16 @@
<delete file="${module.failed}"/>
+ <echo message="Using config:${config}" level="info"/>
<junit fork="${test.fork}" maxmemory="${test.mem}" reloading="no"
haltonfailure="${haltonfailure}" haltonerror="${haltonerror}"
failureproperty="test.failures" printsummary="on" timeout="600000" >
+ <jvmarg value="${jvm.args}"/>
+
<sysproperty key="amqj.logging.level" value="${amqj.logging.level}"/>
+ <sysproperty key="amqj.protocol.logging.level" value="${amqj.protocol.logging.level}"/>
+ <sysproperty key="log4j.debug" value="${log4j.debug}"/>
<sysproperty key="root.logging.level" value="${root.logging.level}"/>
<sysproperty key="log4j.configuration" value="${log4j.configuration}"/>
<sysproperty key="java.naming.factory.initial" value="${java.naming.factory.initial}"/>
@@ -214,10 +224,11 @@
<sysproperty key="broker.ready" value="${broker.ready}" />
<sysproperty key="test.excludes" value="${test.excludes}"/>
<sysproperty key="test.excludesfile" value="${test.excludesfile}"/>
+ <sysproperty key="test.output" value="${module.results}"/>
<sysproperty key="max_prefetch" value ="${max_prefetch}"/>
<sysproperty key="example.plugin.target" value="${project.root}/build/lib/plugins"/>
- <sysproperty key="QPID_EXAMPLE_HOME" value="${project.root}/broker"/>
- <sysproperty key="QPID_HOME" value="${project.root}/broker"/>
+ <sysproperty key="QPID_EXAMPLE_HOME" value="${project.root}/build"/>
+ <sysproperty key="QPID_HOME" value="${project.root}/build"/>
<formatter type="plain"/>
<formatter type="xml"/>
diff --git a/java/perftests/RunningPerformanceTests.txt b/java/perftests/RunningPerformanceTests.txt
index 54291483bf..2bc9220774 100644
--- a/java/perftests/RunningPerformanceTests.txt
+++ b/java/perftests/RunningPerformanceTests.txt
@@ -7,7 +7,7 @@ Building the Tests (Only develoeprs need to know how to do this).
The performance tests are compiled as part of the Maven build by default, but the performance test scripts are not. There is also an additional step to perform, that generates a convenient Jar file containing all of the test dependencies, to simplify invoking Java with a very long command line. The steps to build the performance test suite are:
1. Cd to the /java/perftests directory.
- 2. Execute: mvn uk.co.thebadgerset:junit-toolkit-maven-plugin:tkscriptgen (this generates the scripts).
+ 2. Execute: mvn org.apache.qpid:junit-toolkit-maven-plugin:tkscriptgen (this generates the scripts).
3. Execute: mvn assembly:assembly
The assembly:assembly step generates a Jar with all the dependecies in it in a file name ending with -all-test-deps.jar, which contains the client code and all its dependencies, plus JUnit and the toolkit test runners. The generated scripts expect to find the jar in the current directory. You can Cd to the /target directory and run the scripts from there. The assembly:assembly step also outputs some archives that contain all the scripts and required Jar for convenient shipping of the test suite. Unpack this anywhere you like and run the tests from there.
diff --git a/java/perftests/build.xml b/java/perftests/build.xml
index d50d062466..0288ef691e 100644
--- a/java/perftests/build.xml
+++ b/java/perftests/build.xml
@@ -24,4 +24,294 @@
<import file="../module.xml"/>
+ <property name="xms" value="-Xms256m"/>
+ <property name="xmx" value="-Xmx1024m"/>
+ <property name="test.logging.level" value="-Damqj.test.logging.level=info"/>
+ <property name="qpid.logging.level" value="-Damqj.logging.level=warn"/>
+ <property name="log4j.config" value="-Dlog4j.configuration=perftests.log4j"/>
+ <property name="properties" value="perftests.properties"/>
+
+ <condition property="results" value="${result-path}/results" else="${project.root}/${module}/results">
+ <isset property="result-path"/>
+ </condition>
+
+ <target name="all-tests" depends="all-queue-tests,all-topic-tests"/>
+
+ <target name="all-queue-tests" depends="Queue-Duration-Persistent,Queue-Concurrent,
+ Queue-Duration,Queue-Latency,Queue-Duration-Transacted,Queue-LargeMessage-Persistent"/>
+
+ <target name="all-topic-tests" depends="Topic-Concurrent,Topic-Duration,Topic-Latency,
+ Topic-Duration-Transacted"/>
+
+ <!-- Queue tests -->
+
+ <!--
+ Send 10000 (.5K) messages and measure the time for receiving 1000 messages (10 intervals)
+ the overall latency is also calculated (See Test * Size Throughput)
+ Note that "Test Throughput" is the average time for receiving 1000 messages
+ -->
+ <target name="Queue-Latency" depends="build" description="Run Queue-Latency">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-n Queue-Latency"/>
+ <arg value="-s[10000]"/>
+ <arg value="-t testPingLatency"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingLatencyTestPerf"/>
+ <arg value="rate=100"/>
+ <arg value="batchSize=1000"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one producer/consumer pair
+ for sending and receiving 10000 transient messages.
+ The test last for 5 minutes.
+ -->
+ <target name="Queue-Duration" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Queue-Duration"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one producer/consumer pair
+ for sending and receiving 10000 0.5K persistent messages.
+ The test last for 5 minutes.
+ -->
+ <target name="Queue-Duration-Persistent" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Queue-Duration-Persistent"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="persistent=true"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one producer/consumer pair
+ for sending and receiving 10000 100K persistent messages.
+ The test last for 5 minutes.
+ -->
+ <target name="Queue-LargeMessage-Persistent" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Queue-LargeMessage-Persistent"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="persistent=true"/>
+ <arg value="messageSize=102400"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one (transacted producer)/(Transacted consumer) pair
+ for sending and receiving 10000 (0.5K) persistent messages.
+ Tx batch size is 100 (consumer and producer)
+ The test last for 5 minutes.
+ -->
+ <target name="Queue-Duration-Transacted" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Queue-Duration-Transacted"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="persistent=true"/>
+ <arg value="transacted=true"/>
+ <arg value="batchSize=100"/>
+ <arg value="consTransacted=true"/>
+ <arg value="commitBatchSize=100"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time for four concurrent producer/receiver pairs to send and receive 1000 transient messages
+ -->
+ <target name="Queue-Concurrent" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-r1"/>
+ <arg value="-n Queue-Concurrent"/>
+ <arg value="-s[1000]"/>
+ <arg value="-c[4]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+
+ <!-- Topic tests -->
+
+ <!--
+ Send 10000 (.5K) messages and measure the time for receiving 1000 messages (10 intervals)
+ the overall latency is also calculated (See Test * Size Throughput)
+ Note that "Test Throughput" is the average time for receiving 1000 messages
+ -->
+ <target name="Topic-Latency" depends="build" description="Run Queue-Latency">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-n Topic-Latency"/>
+ <arg value="-s[10000]"/>
+ <arg value="-t testPingLatency"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingLatencyTestPerf"/>
+ <arg value="rate=100"/>
+ <arg value="batchSize=1000"/>
+ <arg value="messageSize=512"/>
+ <arg value="pubsub=true"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one producer/consumer pair
+ for sending and receiving 10000 transient messages.
+ The test last for 5 minutes.
+ -->
+ <target name="Topic-Duration" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Topic-Duration"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="messageSize=512"/>
+ <arg value="pubsub=true"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time required for one (transacted producer)/(Transacted consumer) pair
+ for sending and receiving 10000 (0.5K) persistent messages.
+ Tx batch size is 100 (consumer and producer)
+ The test last for 5 minutes.
+ -->
+ <target name="Topic-Duration-Transacted" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-d5M"/>
+ <arg value="-n Topic-Duration-Transacted"/>
+ <arg value="-s[1000]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="persistent=true"/>
+ <arg value="transacted=true"/>
+ <arg value="batchSize=100"/>
+ <arg value="consTransacted=true"/>
+ <arg value="commitBatchSize=100"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
+ <!--
+ Measure the time for four concurrent producer/receiver pairs to send and receive 1000 transient messages
+ -->
+ <target name="Topic-Concurrent" depends="build" description="">
+ <java classname="org.apache.qpid.junit.extensions.TKTestRunner" fork="true">
+ <classpath refid="module.test.path"/>
+ <jvmarg value="${xms}"/>
+ <jvmarg value="${xmx}"/>
+ <jvmarg value="${test.logging.level}"/>
+ <jvmarg value="${qpid.logging.level}"/>
+ <jvmarg value="${log4j.config}"/>
+ <!-- args -->
+ <arg value="-r1"/>
+ <arg value="-n Topic-Concurrent"/>
+ <arg value="-s[1000]"/>
+ <arg value="-c[4]"/>
+ <arg value="-t testAsyncPingOk"/>
+ <arg value="-o${results}"/>
+ <arg value="--csv"/>
+ <arg value="org.apache.qpid.ping.PingAsyncTestPerf"/>
+ <arg value="messageSize=512"/>
+ </java>
+ </target>
+
</project>
diff --git a/java/perftests/etc/scripts/Connections.sh b/java/perftests/etc/scripts/Connections.sh
index 5b7e7cd345..17e69166bf 100755
--- a/java/perftests/etc/scripts/Connections.sh
+++ b/java/perftests/etc/scripts/Connections.sh
@@ -1 +1,20 @@
-find . -regex '\.\/[P|T].CT-.*\.sh' -exec {} -o results-Connections/ --csv \;
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+find . -regex '\.\/[P|T].CT-.*\.sh' -exec {} -o results-Connections/ --csv \;
diff --git a/java/perftests/etc/scripts/MessageSize.sh b/java/perftests/etc/scripts/MessageSize.sh
new file mode 100755
index 0000000000..bb10822257
--- /dev/null
+++ b/java/perftests/etc/scripts/MessageSize.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+find . -regex '.*M-Qpid-.*\.sh' -exec {} -o results-messageSize/ --csv $* \;
diff --git a/java/perftests/etc/scripts/Reliability.sh b/java/perftests/etc/scripts/Reliability.sh
index 6a3c26efba..aa192743ed 100755
--- a/java/perftests/etc/scripts/Reliability.sh
+++ b/java/perftests/etc/scripts/Reliability.sh
@@ -17,4 +17,4 @@
# specific language governing permissions and limitations
# under the License.
#
-find . -regex '.*R-Qpid-0[1-2].*\.sh' -exec {} -o results-Reliability/ --csv \; && for i in `seq 1 6` ; do find . -regex '.*R-Qpid-0[3-7].*\.sh' -exec {} -o results-Reliability/ --csv \; ; done
+find . -regex '.*R-Qpid-0[1-2].*\.sh' -exec {} -o results-Reliability/ --csv \; && for i in `seq 1 6` ; do find . -regex '.*R-Qpid-0[3-8].*\.sh' -exec {} -o results-Reliability/ --csv \; ; done
diff --git a/java/perftests/etc/scripts/RunAll.sh b/java/perftests/etc/scripts/RunAll.sh
new file mode 100755
index 0000000000..60c04e3ed7
--- /dev/null
+++ b/java/perftests/etc/scripts/RunAll.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+Connections.sh && \
+JobQueue.sh && \
+Latency.sh && \
+MessageSize.sh && \
+Reliability.sh && \
+Throughput.sh
diff --git a/java/perftests/etc/scripts/Throughput.sh b/java/perftests/etc/scripts/Throughput.sh
index f8b79f0c65..d08ad248a5 100755
--- a/java/perftests/etc/scripts/Throughput.sh
+++ b/java/perftests/etc/scripts/Throughput.sh
@@ -17,4 +17,4 @@
# specific language governing permissions and limitations
# under the License.
#
- find . -regex '.*T.BT-.*\.sh' -exec {} -o 2110rc3-throughput/ --csv $* \;
+find . -regex '.*[P|T].BT-.*\.sh' -exec {} -o results-throughput/ --csv $* \;
diff --git a/java/perftests/pom.xml b/java/perftests/pom.xml
index 5a6f91c0fd..44af699d99 100644
--- a/java/perftests/pom.xml
+++ b/java/perftests/pom.xml
@@ -243,14 +243,18 @@
<!-- Performance Tests. -->
<!-- Transient, P2P Tests -->
+ <!-- Concurrency Tests : What are the effects of increasing consumers from 1...30 consumers -->
<TQCT-Qpid-01>-n TQCT-Qpid-01 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=2000 maxPending=2000000 </TQCT-Qpid-01>
<TQCT-Qpid-02>-n TQCT-Qpid-02 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=2000 maxPending=2000000 </TQCT-Qpid-02>
+ <!-- Latency Tests : What are the effects on latency of increasing consumers from 1...30 consumers -->
<TQCL-Qpid-01>-n TQCL-Qpid-01 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=2000 maxPending=2000000 </TQCL-Qpid-01>
<TQCL-Qpid-02>-n TQCL-Qpid-02 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=2000 maxPending=2000000 </TQCL-Qpid-02>
<!-- <TQC-Qpid-05>-n TQC-Qpid-05 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </TQC-Qpid-05> -->
<!-- <TQC-Qpid-06>-n TQC-Qpid-06 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </TQC-Qpid-06> -->
+
+ <!-- Message Size Tests : Tests sending message from 512b upto 1M with Point to Point messaging -->
<TQM-Qpid-01-512b>-n TQM-Qpid-01-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </TQM-Qpid-01-512b>
<TQM-Qpid-02-512b>-n TQM-Qpid-02-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </TQM-Qpid-02-512b>
<TQM-Qpid-01-1K>-n TQM-Qpid-01-1K -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=1024 destinationCount=1 rate=0 maxPending=2000000 </TQM-Qpid-01-1K>
@@ -269,14 +273,17 @@
<TQM-Qpid-02-1M>-n TQM-Qpid-02-1M -d10M -s[100] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=1048576 destinationCount=1 rate=0 maxPending=100000000</TQM-Qpid-02-1M>
<!-- Transient, Pub/Sub Tests -->
+ <!-- Concurrency Tests : What are the effects of increasing consumers from 1...30 consumers -->
<TTCT-Qpid-01>-n TTCT-Qpid-01 -d1M -s[10] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=40 maxPending=2000000 </TTCT-Qpid-01>
<TTCT-Qpid-02>-n TTCT-Qpid-02 -d1M -s[10] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=40 maxPending=2000000 </TTCT-Qpid-02>
+ <!-- Latency Tests : What are the effects on latency of increasing consumers from 1...30 consumers -->
<TTCL-Qpid-01>-n TTCL-Qpid-01 -d1M -s[10] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=40 maxPending=2000000 </TTCL-Qpid-01>
<TTCL-Qpid-02>-n TTCL-Qpid-02 -d1M -s[10] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=40 maxPending=2000000 </TTCL-Qpid-02>
<!-- <TTC-Qpid-05>-n TTC-Qpid-05 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </TTC-Qpid-05> -->
<!-- <TTC-Qpid-06>-n TTC-Qpid-06 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </TTC-Qpid-06> -->
+ <!-- Message Size Tests : Tests sending message from 512b upto 1M with Point to Point messaging -->
<TTM-Qpid-01-512b>-n TTM-Qpid-01-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </TTM-Qpid-01-512b>
<TTM-Qpid-02-512b>-n TTM-Qpid-02-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </TTM-Qpid-02-512b>
<TTM-Qpid-01-1K>-n TTM-Qpid-01-1K -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=1024 destinationCount=1 rate=0 maxPending=2000000 </TTM-Qpid-01-1K>
@@ -295,14 +302,17 @@
<TTM-Qpid-02-1M>-n TTM-Qpid-02-1M -d10M -s[4] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=false pubsub=true uniqueDests=false numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=1048476 destinationCount=1 rate=0 maxPending=20000000</TTM-Qpid-02-1M>
<!-- Persistent, P2P Tests -->
+ <!-- Concurrency Tests : What are the effects of increasing consumers from 1...30 consumers -->
<PQCT-Qpid-01>-n PQCT-Qpid-01 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=600 maxPending=2000000 </PQCT-Qpid-01>
<PQCT-Qpid-02>-n PQCT-Qpid-02 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=100 maxPending=2000000 </PQCT-Qpid-02>
+ <!-- Latency Tests : What are the effects on latency of increasing consumers from 1...30 consumers -->
<PQCL-Qpid-01>-n PQCL-Qpid-01 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=600 maxPending=2000000 </PQCL-Qpid-01>
<PQCL-Qpid-02>-n PQCL-Qpid-02 -d1M -s[1000] -c[1:30]:samples=30 -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=1 rate=100 maxPending=2000000 </PQCL-Qpid-02>
<!-- <PQC-Qpid-05>-n PQC-Qpid-05 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </PQC-Qpid-05> -->
<!-- <PQC-Qpid-06>-n PQC-Qpid-06 -d10M -s[10] -c[100] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=256 destinationCount=10 rate=0 maxPending=100000 </PQC-Qpid-06> -->
+ <!-- Message Size Tests : Tests sending message from 512b upto 1M with Point to Point messaging -->
<PQM-Qpid-01-512b>-n PQM-Qpid-01-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </PQM-Qpid-01-512b>
<PQM-Qpid-02-512b>-n PQM-Qpid-02-512b -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=false consTransacted=false consAckMode=1 commitBatchSize=10 batchSize=1000 messageSize=512 destinationCount=1 rate=0 maxPending=2000000 </PQM-Qpid-02-512b>
<PQM-Qpid-01-1K>-n PQM-Qpid-01-1K -d10M -s[1000] -c[8] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=false uniqueDests=true numConsumers=1 transacted=true consTransacted=true consAckMode=0 commitBatchSize=10 batchSize=1000 messageSize=1024 destinationCount=1 rate=0 maxPending=2000000 </PQM-Qpid-01-1K>
@@ -360,6 +370,7 @@
<PTBT-TX-Qpid-01>-n PTBT-TX-Qpid-01 -d10M -s[1000] -c[2] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true uniqueDests=false numConsumers=8 transacted=true consTransacted=false consAckMode=1 commitBatchSize=1 batchSize=1000 messageSize=256 destinationCount=1 rate=0 maxPending=2000000 </PTBT-TX-Qpid-01>
<PTBT-AA-Qpid-01>-n PTBT-AA-Qpid-01 -d10M -s[1000] -c[2] -o $QPID_WORK/results -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true uniqueDests=false numConsumers=8 transacted=false consTransacted=false consAckMode=1 commitBatchSize=1 batchSize=1000 messageSize=256 destinationCount=1 rate=0 maxPending=2000000 </PTBT-AA-Qpid-01>
+ <!-- Benchmark Latency testing-->
<!-- Job Queueing. 1:10 -->
<TQBL-AA-Qpid-02-01>-n TQBL-AA-Qpid-02 -d1M -s[1000] -c[1] -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=10 transacted=false consTransacted=false consAckMode=1 commitBatchSize=1 batchSize=1000 messageSize=5120 destinationCount=1 rate=1000 maxPending=2000000 </TQBL-AA-Qpid-02-01>
<TQBL-AA-Qpid-02-02>-n TQBL-AA-Qpid-02 -d1M -s[1000] -c[1] -o $QPID_WORK/results -t testPingLatency org.apache.qpid.ping.PingLatencyTestPerf persistent=false pubsub=false uniqueDests=true numConsumers=10 transacted=false consTransacted=false consAckMode=1 commitBatchSize=1 batchSize=1000 messageSize=5120 destinationCount=1 rate=2000 maxPending=2000000 </TQBL-AA-Qpid-02-02>
diff --git a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java b/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
index 64ccb719b6..3ad6c021bd 100644
--- a/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
+++ b/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
@@ -29,7 +29,6 @@ import javax.jms.ObjectMessage;
import javax.jms.StreamMessage;
import javax.jms.BytesMessage;
import javax.jms.TextMessage;
-import javax.jms.Queue;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
@@ -42,10 +41,10 @@ public class TestMessageFactory
return session.createTextMessage(createMessagePayload(size));
}
- public static JMSTextMessage newJMSTextMessage(int size, String encoding) throws JMSException
+ public static TextMessage newJMSTextMessage(Session session, int size, String encoding) throws JMSException
{
- ByteBuffer byteBuffer = (new SimpleByteBufferAllocator()).allocate(size, true);
- JMSTextMessage message = new JMSTextMessage(byteBuffer, encoding);
+
+ TextMessage message = session.createTextMessage();
message.clearBody();
message.setText(createMessagePayload(size));
return message;
diff --git a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
index 4d8a736ec8..f994cd138e 100644
--- a/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
+++ b/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
@@ -1673,11 +1673,9 @@ public class PingPongProducer implements Runnable, ExceptionListener
*/
public int getExpectedNumPings(int numpings)
{
- // log.debug("public int getExpectedNumPings(int numpings = " + numpings + "): called");
-
- // log.debug("Each ping will be received by " + (_isPubSub ? getConsumersPerDestination() : 1) + " consumers.");
-
- return numpings * (_isPubSub ? getConsumersPerDestination() : 1);
+ // Wow, I'm freaking sorry about this return here...
+ return ((_failAfterSend || _failBeforeCommit) ? numpings - 1: numpings) *
+ (_isPubSub ? getConsumersPerDestination() : 1);
}
/**
diff --git a/java/systests/pom.xml b/java/systests/pom.xml
index 49f088ec1a..73c8fb7351 100644
--- a/java/systests/pom.xml
+++ b/java/systests/pom.xml
@@ -151,7 +151,6 @@
<MessageReturnTest>-n MessageReturnTest org.apache.qpid.server.queue.MessageReturnTest </MessageReturnTest>
<QueueDepthWithSelectorTest>-n QueueDepthWithSelectorTest org.apache.qpid.server.queue.QueueDepthWithSelectorTest </QueueDepthWithSelectorTest>
<!--<SubscriptionManagerTest>-n SubscriptionManagerTest org.apache.qpid.server.queue.SubscriptionManagerTest </SubscriptionManagerTest>-->
- <SubscriptionSetTest>-n SubscriptionSetTest org.apache.qpid.server.queue.SubscriptionSetTest </SubscriptionSetTest>
<TimeToLiveTest>-n TimeToLiveTest org.apache.qpid.server.queue.TimeToLiveTest </TimeToLiveTest>
<TxnBufferTest>-n TxnBufferTest org.apache.qpid.server.txn.TxnBufferTest </TxnBufferTest>
<!--<TxnTest>-n TxnTest org.apache.qpid.server.txn.TxnTest </TxnTest>-->
diff --git a/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java b/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
new file mode 100644
index 0000000000..5323ad28bf
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeIdleStatusChecker.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.mina.transport.vmpipe.support;
+
+import org.apache.mina.common.IdleStatus;
+
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This file is a patch to override MINA, because of the IdentityHashMap bug. Workaround to be supplied in MINA 1.0.7.
+ * This patched file will be removed once upgraded onto a newer MINA.
+ *
+ * Dectects idle sessions and fires <tt>sessionIdle</tt> events to them.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ */
+public class VmPipeIdleStatusChecker
+{
+ private static final VmPipeIdleStatusChecker INSTANCE = new VmPipeIdleStatusChecker();
+
+ public static VmPipeIdleStatusChecker getInstance()
+ {
+ return INSTANCE;
+ }
+
+ private final Map sessions = new HashMap(); // will use as a set
+
+ private final Worker worker = new Worker();
+
+ private VmPipeIdleStatusChecker()
+ {
+ worker.start();
+ }
+
+ public void addSession(VmPipeSessionImpl session)
+ {
+ synchronized (sessions)
+ {
+ sessions.put(session, session);
+ }
+ }
+
+ private class Worker extends Thread
+ {
+ private Worker()
+ {
+ super("VmPipeIdleStatusChecker");
+ setDaemon(true);
+ }
+
+ public void run()
+ {
+ for (;;)
+ {
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ { }
+
+ long currentTime = System.currentTimeMillis();
+
+ synchronized (sessions)
+ {
+ Iterator it = sessions.keySet().iterator();
+ while (it.hasNext())
+ {
+ VmPipeSessionImpl session = (VmPipeSessionImpl) it.next();
+ if (!session.isConnected())
+ {
+ it.remove();
+ }
+ else
+ {
+ notifyIdleSession(session, currentTime);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyIdleSession(VmPipeSessionImpl session, long currentTime)
+ {
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE), IdleStatus.BOTH_IDLE,
+ Math.max(session.getLastIoTime(), session.getLastIdleTime(IdleStatus.BOTH_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.READER_IDLE), IdleStatus.READER_IDLE,
+ Math.max(session.getLastReadTime(), session.getLastIdleTime(IdleStatus.READER_IDLE)));
+ notifyIdleSession0(session, currentTime, session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE), IdleStatus.WRITER_IDLE,
+ Math.max(session.getLastWriteTime(), session.getLastIdleTime(IdleStatus.WRITER_IDLE)));
+ }
+
+ private void notifyIdleSession0(VmPipeSessionImpl session, long currentTime, long idleTime, IdleStatus status,
+ long lastIoTime)
+ {
+ if ((idleTime > 0) && (lastIoTime != 0) && ((currentTime - lastIoTime) >= idleTime))
+ {
+ session.increaseIdleCount(status);
+ session.getFilterChain().fireSessionIdle(session, status);
+ }
+ }
+
+}
diff --git a/java/client/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
index fe418535d6..fe418535d6 100644
--- a/java/client/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
diff --git a/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java
index 7cca22de6c..7cca22de6c 100644
--- a/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/DispatcherTest.java
diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java
index 7461f6c200..7461f6c200 100644
--- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java
diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
index 136b9b94b6..b438304892 100644
--- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
@@ -20,17 +20,12 @@
*/
package org.apache.qpid.client;
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
@@ -38,9 +33,7 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.naming.Context;
-import javax.naming.spi.InitialContextFactory;
-import java.util.Hashtable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -206,16 +199,27 @@ public class MessageListenerMultiConsumerTest extends QpidTestCase
MessageConsumer consumer2 = _clientSession1.createConsumer(_queue);
- for (int msg = 0; msg < (MSG_COUNT / 2); msg++)
+ int msg;
+ for (msg = 0; msg < (MSG_COUNT / 2); msg++)
{
- assertTrue(_consumer1.receive(3000) != null);
+
+ final Message message = _consumer1.receive(1000);
+ if(message == null)
+ {
+ break;
+ }
+
}
- for (int msg = 0; msg < (MSG_COUNT / 2); msg++)
+ _consumer1.close();
+ _clientSession1.close();
+
+ for (; msg < MSG_COUNT ; msg++)
{
- assertTrue(consumer2.receive(3000) != null);
+ assertTrue("Failed at msg id" + msg, _consumer2.receive(1000) != null);
}
+
}
else
{
diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java
index 12b84b1495..e1c0f0ccef 100644
--- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/MessageListenerTest.java
@@ -20,17 +20,12 @@
*/
package org.apache.qpid.client;
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
@@ -38,9 +33,7 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.naming.Context;
-import javax.naming.spi.InitialContextFactory;
-import java.util.Hashtable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -132,16 +125,16 @@ public class MessageListenerTest extends QpidTestCase implements MessageListener
}
- public void testRecieveTheUseMessageListener() throws Exception
+ public void testRecieveThenUseMessageListener() throws Exception
{
_logger.error("Test disabled as initial receive is not called first");
// Perform initial receive to start connection
- // assertTrue(_consumer.receive(2000) != null);
- // receivedCount++;
+ assertTrue(_consumer.receive(2000) != null);
+ receivedCount++;
// Sleep to ensure remaining 4 msgs end up on _synchronousQueue
- // Thread.sleep(1000);
+ Thread.sleep(1000);
// Set the message listener and wait for the messages to come in.
_consumer.setMessageListener(this);
diff --git a/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java
index c920499a07..a0bb31192f 100644
--- a/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/ResetMessageListenerTest.java
@@ -20,17 +20,12 @@
*/
package org.apache.qpid.client;
-import junit.framework.TestCase;
-
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
@@ -40,9 +35,7 @@ import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
-import javax.naming.spi.InitialContextFactory;
-import java.util.Hashtable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
diff --git a/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java b/java/systests/src/main/java/org/apache/qpid/client/message/NonQpidObjectMessage.java
index 60a26c8e62..857adaf82c 100644
--- a/java/client/src/test/java/org/apache/qpid/client/message/NonQpidObjectMessage.java
+++ b/java/systests/src/main/java/org/apache/qpid/client/message/NonQpidObjectMessage.java
@@ -26,20 +26,22 @@ import java.util.Enumeration;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
+import javax.jms.Session;
public class NonQpidObjectMessage implements ObjectMessage {
- private JMSObjectMessage _realMessage;
+ private ObjectMessage _realMessage;
private String _contentString;
/**
* Allows us to construct a JMS message which
* does not inherit from the Qpid message superclasses
* and expand our unit testing of MessageConverter et al
+ * @param session
*/
- public NonQpidObjectMessage()
+ public NonQpidObjectMessage(Session session) throws JMSException
{
- _realMessage = new JMSObjectMessage();
+ _realMessage = session.createObjectMessage();
}
public String getJMSMessageID() throws JMSException {
diff --git a/java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java b/java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java
index 2bb16aff2e..aafddb810a 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/ack/TxAckTest.java
@@ -26,12 +26,16 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.store.MemoryMessageStore;
+import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.MessageHandleFactory;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.store.TestMemoryMessageStore;
import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.txn.TransactionalContext;
@@ -99,12 +103,16 @@ public class TxAckTest extends TestCase
private final List<Long> _unacked;
private StoreContext _storeContext = new StoreContext();
- Scenario(int messageCount, List<Long> acked, List<Long> unacked)
+ Scenario(int messageCount, List<Long> acked, List<Long> unacked) throws Exception
{
- TransactionalContext txnContext = new NonTransactionalContext(new MemoryMessageStore(),
+ TransactionalContext txnContext = new NonTransactionalContext(new TestMemoryMessageStore(),
_storeContext, null,
new LinkedList<RequiredDeliveryException>()
);
+ AMQQueue queue =
+ AMQQueueFactory.createAMQQueueImpl(new AMQShortString("test"), false, null, false, new VirtualHost("test", new MemoryMessageStore()),
+ null);
+
for (int i = 0; i < messageCount; i++)
{
long deliveryTag = i + 1;
@@ -138,8 +146,8 @@ public class TxAckTest extends TestCase
}
};
- TestMessage message = new TestMessage(deliveryTag, i, info, txnContext);
- _map.add(deliveryTag, new UnacknowledgedMessage(new QueueEntry(null,message), null, deliveryTag, _map));
+ TestMessage message = new TestMessage(deliveryTag, i, info, txnContext.getStoreContext());
+ _map.add(deliveryTag, queue.enqueue(new StoreContext(), message));
}
_acked = acked;
_unacked = unacked;
@@ -154,7 +162,7 @@ public class TxAckTest extends TestCase
{
for (long tag : tags)
{
- UnacknowledgedMessage u = _map.get(tag);
+ QueueEntry u = _map.get(tag);
assertTrue("Message not found for tag " + tag, u != null);
((TestMessage) u.getMessage()).assertCountEquals(expected);
}
@@ -175,7 +183,7 @@ public class TxAckTest extends TestCase
_op.consolidate();
_op.undoPrepare();
- assertCount(_acked, 1); //DTX Changed to 0, but that is wrong msg 5 is acked!
+ assertCount(_acked, 1);
assertCount(_unacked, 0);
}
@@ -195,34 +203,50 @@ public class TxAckTest extends TestCase
}
}
+ private static AMQMessageHandle createMessageHandle(final long messageId, final MessagePublishInfo publishBody)
+ {
+ final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
+ null,
+ false);
+ try
+ {
+ amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),
+ publishBody,
+ new ContentHeaderBody()
+ {
+ public int getSize()
+ {
+ return 1;
+ }
+ });
+ }
+ catch (AMQException e)
+ {
+ // won't happen
+ }
+
+
+ return amqMessageHandle;
+ }
+
+
private class TestMessage extends AMQMessage
{
private final long _tag;
private int _count;
- TestMessage(long tag, long messageId, MessagePublishInfo publishBody, TransactionalContext txnContext)
+ TestMessage(long tag, long messageId, MessagePublishInfo publishBody, StoreContext storeContext)
+ throws AMQException
{
- super(messageId, publishBody, txnContext);
- try
- {
- setContentHeaderBody(new ContentHeaderBody()
- {
- public int getSize()
- {
- return 1;
- }
- });
- }
- catch (AMQException e)
- {
- // won't happen
- }
+ super(createMessageHandle(messageId, publishBody), storeContext, publishBody);
_tag = tag;
}
- public void incrementReference()
+
+ public boolean incrementReference()
{
_count++;
+ return true;
}
public void decrementReference(StoreContext context)
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
index 0968f0c468..adb7a7cd0c 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
@@ -24,18 +24,17 @@ import junit.framework.TestCase;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.*;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.SkeletonMessageStore;
import org.apache.qpid.server.store.MemoryMessageStore;
import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.store.SkeletonMessageStore;
import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.RequiredDeliveryException;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.log4j.Logger;
import java.util.*;
@@ -50,7 +49,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase
/**
* Not used in this test, just there to stub out the routing calls
*/
- private MessageStore _store = new SkeletonMessageStore();
+ private MessageStore _store = new MemoryMessageStore();
private StoreContext _storeContext = new StoreContext();
@@ -94,7 +93,11 @@ public class AbstractHeadersExchangeTestBase extends TestCase
protected void route(Message m) throws AMQException
{
m.route(exchange);
- m.routingComplete(_store, _storeContext, _handleFactory);
+ m.getIncomingMessage().routingComplete(_store, _handleFactory);
+ if(m.getIncomingMessage().allContentReceived())
+ {
+ m.getIncomingMessage().deliverToQueues();
+ }
}
protected void routeAndTest(Message m, TestQueue... expected) throws AMQException
@@ -122,12 +125,12 @@ public class AbstractHeadersExchangeTestBase extends TestCase
{
if (expected.contains(q))
{
- assertTrue("Expected " + m + " to be delivered to " + q, m.isInQueue(q));
+ assertTrue("Expected " + m + " to be delivered to " + q, q.isInQueue(m));
//assert m.isInQueue(q) : "Expected " + m + " to be delivered to " + q;
}
else
{
- assertFalse("Did not expect " + m + " to be delivered to " + q, m.isInQueue(q));
+ assertFalse("Did not expect " + m + " to be delivered to " + q, q.isInQueue(m));
//assert !m.isInQueue(q) : "Did not expect " + m + " to be delivered to " + q;
}
}
@@ -234,7 +237,7 @@ public class AbstractHeadersExchangeTestBase extends TestCase
return properties;
}
- static class TestQueue extends AMQQueue
+ static class TestQueue extends SimpleAMQQueue
{
final List<HeadersExchangeTest.Message> messages = new ArrayList<HeadersExchangeTest.Message>();
@@ -248,13 +251,167 @@ public class AbstractHeadersExchangeTestBase extends TestCase
* not invoked. It is unnecessary since for this test we only care to know whether the message was
* sent to the queue; the queue processing logic is not being tested.
* @param msg
- * @param deliverFirst
* @throws AMQException
*/
- public void process(StoreContext context, QueueEntry msg, boolean deliverFirst) throws AMQException
+ @Override
+ public QueueEntry enqueue(StoreContext context, AMQMessage msg) throws AMQException
+ {
+ messages.add( new HeadersExchangeTest.Message(msg));
+ return new QueueEntry()
+ {
+
+ public AMQQueue getQueue()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public AMQMessage getMessage()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public long getSize()
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean getDeliveredToConsumer()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean expired() throws AMQException
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isAcquired()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean acquire()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean acquire(Subscription sub)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean delete()
+ {
+ return false;
+ }
+
+ public boolean isDeleted()
+ {
+ return false;
+ }
+
+ public boolean acquiredBySubscription()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setDeliveredToSubscription()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void release()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public String debugIdentity()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean immediateAndNotDelivered()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void setRedelivered(boolean b)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Subscription getDeliveredSubscription()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void reject()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void reject(Subscription subscription)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isRejectedBy(Subscription subscription)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void requeue(StoreContext storeContext) throws AMQException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void dequeue(final StoreContext storeContext) throws FailedDequeueException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void dispose(final StoreContext storeContext) throws MessageCleanupException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void restoreCredit()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void discard(StoreContext storeContext) throws FailedDequeueException, MessageCleanupException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isQueueDeleted()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void addStateChangeListener(StateChangeListener listener)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean removeStateChangeListener(StateChangeListener listener)
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public int compareTo(final QueueEntry o)
+ {
+ return 0; //To change body of implemented methods use File | Settings | File Templates.
+ }
+ };
+ }
+
+ boolean isInQueue(Message msg)
{
- messages.add(new HeadersExchangeTest.Message(msg.getMessage()));
+ return messages.contains(msg);
}
+
}
/**
@@ -262,10 +419,44 @@ public class AbstractHeadersExchangeTestBase extends TestCase
*/
static class Message extends AMQMessage
{
- private static MessageStore _messageStore = new MemoryMessageStore();
+ private class TestIncomingMessage extends IncomingMessage
+ {
+
+ public TestIncomingMessage(final long messageId,
+ final MessagePublishInfo info,
+ final TransactionalContext txnContext,
+ final AMQProtocolSession publisher)
+ {
+ super(messageId, info, txnContext, publisher);
+ }
+
+
+ public AMQMessage getUnderlyingMessage()
+ {
+ return Message.this;
+ }
+
+
+ public ContentHeaderBody getContentHeaderBody()
+ {
+ try
+ {
+ return Message.this.getContentHeaderBody();
+ }
+ catch (AMQException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private IncomingMessage _incoming;
+
+ private static MessageStore _messageStore = new SkeletonMessageStore();
private static StoreContext _storeContext = new StoreContext();
+
private static TransactionalContext _txnContext = new NonTransactionalContext(_messageStore, _storeContext,
null,
new LinkedList<RequiredDeliveryException>()
@@ -278,12 +469,47 @@ public class AbstractHeadersExchangeTestBase extends TestCase
Message(String id, FieldTable headers) throws AMQException
{
- this(getPublishRequest(id), getContentHeader(headers), null);
+ this(_messageStore.getNewMessageId(),getPublishRequest(id), getContentHeader(headers), null);
+ }
+
+ public IncomingMessage getIncomingMessage()
+ {
+ return _incoming;
+ }
+
+ private Message(long messageId,
+ MessagePublishInfo publish,
+ ContentHeaderBody header,
+ List<ContentBody> bodies) throws AMQException
+ {
+ super(createMessageHandle(messageId, publish, header), _txnContext.getStoreContext(), publish);
+
+
+
+ _incoming = new TestIncomingMessage(getMessageId(),publish,_txnContext,new MockProtocolSession(_messageStore));
+ _incoming.setContentHeaderBody(header);
+
+
}
- private Message(MessagePublishInfo publish, ContentHeaderBody header, List<ContentBody> bodies) throws AMQException
+ private static AMQMessageHandle createMessageHandle(final long messageId,
+ final MessagePublishInfo publish,
+ final ContentHeaderBody header)
{
- super(_messageStore.getNewMessageId(), publish, _txnContext, header);
+
+ final AMQMessageHandle amqMessageHandle = (new MessageHandleFactory()).createMessageHandle(messageId,
+ _messageStore,
+ true);
+
+ try
+ {
+ amqMessageHandle.setPublishAndContentHeaderBody(new StoreContext(),publish,header);
+ }
+ catch (AMQException e)
+ {
+
+ }
+ return amqMessageHandle;
}
private Message(AMQMessage msg) throws AMQException
@@ -291,15 +517,13 @@ public class AbstractHeadersExchangeTestBase extends TestCase
super(msg);
}
+
+
void route(Exchange exchange) throws AMQException
{
- exchange.route(this);
+ exchange.route(_incoming);
}
- boolean isInQueue(TestQueue queue)
- {
- return queue.messages.contains(this);
- }
public int hashCode()
{
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
index eca642b556..fd11ddeae2 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java
@@ -30,7 +30,12 @@ public class HeadersExchangeTest extends AbstractHeadersExchangeTestBase
protected void setUp() throws Exception
{
super.setUp();
- ApplicationRegistry.initialise(new NullApplicationRegistry());
+ ApplicationRegistry.initialise(new NullApplicationRegistry(), 1);
+ }
+
+ protected void tearDown()
+ {
+ ApplicationRegistry.remove(1);
}
public void testSimple() throws AMQException
diff --git a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
index bae3f844d7..e14efe03a7 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
@@ -29,13 +29,16 @@ import org.apache.qpid.client.*;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.BindingURL;
+import org.apache.qpid.url.URLSyntaxException;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.AMQException;
import javax.jms.*;
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
+import java.net.URISyntaxException;
public class ReturnUnroutableMandatoryMessageTest extends TestCase implements ExceptionListener
{
@@ -68,6 +71,7 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
{
super.tearDown();
TransportConnection.killAllVMBrokers();
+ ApplicationRegistry.remove(1);
}
/**
@@ -75,78 +79,90 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
*
* @throws Exception
*/
- public void testReturnUnroutableMandatoryMessage_HEADERS() throws Exception
+ public void testReturnUnroutableMandatoryMessage_HEADERS() throws URISyntaxException, AMQException, JMSException
{
_bouncedMessageList.clear();
- Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
-
- AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- AMQHeadersExchange queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS + "://" + ExchangeDefaults.HEADERS_EXCHANGE_NAME + "/test/queue1?" + BindingURL.OPTION_ROUTING_KEY + "='F0000=1'"));
- FieldTable ft = new FieldTable();
- ft.setString("F1000", "1");
- MessageConsumer consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String) null, ft);
-
- //force synch to ensure the consumer has resulted in a bound queue
- //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
- // This is the default now
-
- Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
-
- con2.setExceptionListener(this);
- AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- // Need to start the "producer" connection in order to receive bounced messages
- _logger.info("Starting producer connection");
- con2.start();
-
+ MessageConsumer consumer = null;
+ AMQSession producerSession = null;
+ AMQHeadersExchange queue = null;
+ Connection con=null, con2 = null;
+ try
+ {
+ con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
- MessageProducer nonMandatoryProducer = producerSession.createProducer(queue, false, false);
- MessageProducer mandatoryProducer = producerSession.createProducer(queue);
+ AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- // First test - should neither be bounced nor routed
- _logger.info("Sending non-routable non-mandatory message");
- TextMessage msg1 = producerSession.createTextMessage("msg1");
- nonMandatoryProducer.send(msg1);
+ queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS + "://" + ExchangeDefaults.HEADERS_EXCHANGE_NAME + "/test/queue1?" + BindingURL.OPTION_ROUTING_KEY + "='F0000=1'"));
+ FieldTable ft = new FieldTable();
+ ft.setString("F1000", "1");
+ consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String) null, ft);
- // Second test - should be bounced
- _logger.info("Sending non-routable mandatory message");
- TextMessage msg2 = producerSession.createTextMessage("msg2");
- mandatoryProducer.send(msg2);
+ //force synch to ensure the consumer has resulted in a bound queue
+ //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
+ // This is the default now
- // Third test - should be routed
- _logger.info("Sending routable message");
- TextMessage msg3 = producerSession.createTextMessage("msg3");
- msg3.setStringProperty("F1000", "1");
- mandatoryProducer.send(msg3);
+ con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
+ con2.setExceptionListener(this);
+ producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- _logger.info("Starting consumer connection");
- con.start();
- TextMessage tm = (TextMessage) consumer.receive(1000L);
-
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg3".equals(tm.getText()));
+ // Need to start the "producer" connection in order to receive bounced messages
+ _logger.info("Starting producer connection");
+ con2.start();
+ }
+ catch (JMSException jmse)
+ {
+ fail(jmse.getMessage());
+ }
try
{
- Thread.sleep(1000L);
+ MessageProducer nonMandatoryProducer = producerSession.createProducer(queue, false, false);
+ MessageProducer mandatoryProducer = producerSession.createProducer(queue);
+
+ // First test - should neither be bounced nor routed
+ _logger.info("Sending non-routable non-mandatory message");
+ TextMessage msg1 = producerSession.createTextMessage("msg1");
+ nonMandatoryProducer.send(msg1);
+
+ // Second test - should be bounced
+ _logger.info("Sending non-routable mandatory message");
+ TextMessage msg2 = producerSession.createTextMessage("msg2");
+ mandatoryProducer.send(msg2);
+
+ // Third test - should be routed
+ _logger.info("Sending routable message");
+ TextMessage msg3 = producerSession.createTextMessage("msg3");
+ msg3.setStringProperty("F1000", "1");
+ mandatoryProducer.send(msg3);
+
+ _logger.info("Starting consumer connection");
+ con.start();
+ TextMessage tm = (TextMessage) consumer.receive(1000L);
+
+ assertTrue("No message routed to receiver", tm != null);
+ assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg3".equals(tm.getText()));
+
+ try
+ {
+ Thread.sleep(1000L);
+ }
+ catch (InterruptedException e)
+ {
+ ;
+ }
+
+ assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
+ Message m = _bouncedMessageList.get(0);
+ assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
}
- catch (InterruptedException e)
+ catch (JMSException jmse)
{
- ;
- }
-
- assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
- Message m = _bouncedMessageList.get(0);
- assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
+ }
con.close();
con2.close();
-
}
public void testReturnUnroutableMandatoryMessage_QUEUE() throws Exception
@@ -154,7 +170,6 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
_bouncedMessageList.clear();
Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
AMQQueue valid_queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "testReturnUnroutableMandatoryMessage_QUEUE");
@@ -174,7 +189,6 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
_logger.info("Starting producer connection");
con2.start();
-
MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_queue, false, false);
MessageProducer mandatoryProducer = producerSession.createProducer(invalid_queue);
@@ -188,7 +202,6 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
TextMessage msg2 = producerSession.createTextMessage("msg2");
mandatoryProducer.send(msg2);
-
_logger.info("Starting consumer connection");
con.start();
TextMessage tm = (TextMessage) consumer.receive(1000L);
@@ -209,18 +222,15 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
Message m = _bouncedMessageList.get(0);
assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
con.close();
con2.close();
}
-
public void testReturnUnroutableMandatoryMessage_TOPIC() throws Exception
{
_bouncedMessageList.clear();
Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
AMQTopic valid_topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, "test.Return.Unroutable.Mandatory.Message.TOPIC");
@@ -240,7 +250,6 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
_logger.info("Starting producer connection");
con2.start();
-
MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_topic, false, false);
MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic);
@@ -254,7 +263,6 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
TextMessage msg2 = producerSession.createTextMessage("msg2");
mandatoryProducer.send(msg2);
-
_logger.info("Starting consumer connection");
con.start();
TextMessage tm = (TextMessage) consumer.receive(1000L);
@@ -275,12 +283,10 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
Message m = _bouncedMessageList.get(0);
assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
con.close();
con2.close();
}
-
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(ReturnUnroutableMandatoryMessageTest.class);
@@ -293,7 +299,8 @@ public class ReturnUnroutableMandatoryMessageTest extends TestCase implements Ex
try
{
linkedException = jmsException.getLinkedException();
- } catch (Exception e)
+ }
+ catch (Exception e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java b/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java
index 012a983be5..22a1b119fa 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java
@@ -22,7 +22,7 @@
package org.apache.qpid.server.failure;
import junit.framework.TestCase;
-import org.apache.qpid.testutil.QpidClientConnectionHelper;
+import org.apache.qpid.test.utils.QpidClientConnectionHelper;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
diff --git a/java/systests/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/java/systests/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
index e4555e020e..8e7038eec3 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java
@@ -28,16 +28,15 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.codec.AMQCodecFactory;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.queue.AMQQueueFactory;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.SkeletonMessageStore;
-import org.apache.qpid.server.virtualhost.VirtualHost;
import javax.management.JMException;
-
/**
* Test class to test MBean operations for AMQMinaProtocolSession.
*/
@@ -56,13 +55,12 @@ public class AMQProtocolSessionMBeanTest extends TestCase
// check the channel count is correct
int channelCount = _mbean.channels().size();
assertTrue(channelCount == 1);
- AMQQueue queue = new org.apache.qpid.server.queue.AMQQueue(new AMQShortString("testQueue_" + System.currentTimeMillis()),
+ AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue_" + System.currentTimeMillis()),
false,
new AMQShortString("test"),
true,
- _protocolSession.getVirtualHost());
- AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore);
-
+ _protocolSession.getVirtualHost(), null);
+ AMQChannel channel = new AMQChannel(_protocolSession,2, _messageStore);
channel.setDefaultQueue(queue);
_protocolSession.addChannel(channel);
channelCount = _mbean.channels().size();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java
index 2416442b10..9c2932c5e2 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/AckTest.java
@@ -23,24 +23,28 @@ package org.apache.qpid.server.queue;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.RequiredDeliveryException;
-import org.apache.qpid.server.ack.UnacknowledgedMessage;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
+import org.apache.qpid.server.flow.LimitlessCreditManager;
+import org.apache.qpid.server.flow.Pre0_10CreditManager;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.store.TestMemoryMessageStore;
import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
import org.apache.qpid.server.txn.NonTransactionalContext;
import org.apache.qpid.server.txn.TransactionalContext;
import org.apache.qpid.server.util.NullApplicationRegistry;
-import java.util.HashSet;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Set;
+import java.util.Collections;
/**
* Tests that acknowledgements are handled correctly.
@@ -49,37 +53,38 @@ public class AckTest extends TestCase
{
private static final Logger _log = Logger.getLogger(AckTest.class);
- private SubscriptionImpl _subscription;
+ private Subscription _subscription;
private MockProtocolSession _protocolSession;
- private TestableMemoryMessageStore _messageStore;
+ private TestMemoryMessageStore _messageStore;
private StoreContext _storeContext = new StoreContext();
private AMQChannel _channel;
- private SubscriptionSet _subscriptionManager;
-
private AMQQueue _queue;
private static final AMQShortString DEFAULT_CONSUMER_TAG = new AMQShortString("conTag");
- public AckTest() throws Exception
- {
- ApplicationRegistry.initialise(new NullApplicationRegistry());
- }
-
protected void setUp() throws Exception
{
super.setUp();
- _messageStore = new TestableMemoryMessageStore();
+ ApplicationRegistry.initialise(new NullApplicationRegistry(), 1);
+
+ _messageStore = new TestMemoryMessageStore();
_protocolSession = new MockProtocolSession(_messageStore);
- _channel = new AMQChannel(_protocolSession, 5, _messageStore);
+ _channel = new AMQChannel(_protocolSession,5, _messageStore /*dont need exchange registry*/);
_protocolSession.addChannel(_channel);
- _subscriptionManager = new SubscriptionSet();
- _queue = new AMQQueue(new AMQShortString("myQ"), false, new AMQShortString("guest"), true, ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), _subscriptionManager);
+
+ _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("myQ"), false, new AMQShortString("guest"), true, ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"),
+ null);
+ }
+
+ protected void tearDown()
+ {
+ ApplicationRegistry.remove(1);
}
private void publishMessages(int count) throws AMQException
@@ -92,6 +97,7 @@ public class AckTest extends TestCase
TransactionalContext txnContext = new NonTransactionalContext(_messageStore, _storeContext, null,
new LinkedList<RequiredDeliveryException>()
);
+ _queue.registerSubscription(_subscription,false);
MessageHandleFactory factory = new MessageHandleFactory();
for (int i = 1; i <= count; i++)
{
@@ -125,7 +131,8 @@ public class AckTest extends TestCase
return new AMQShortString("rk");
}
};
- AMQMessage msg = new AMQMessage(_messageStore.getNewMessageId(), publishBody, txnContext);
+ IncomingMessage msg = new IncomingMessage(_messageStore.getNewMessageId(), publishBody, txnContext,_protocolSession);
+ //IncomingMessage msg2 = null;
if (persistent)
{
BasicContentHeaderProperties b = new BasicContentHeaderProperties();
@@ -142,10 +149,16 @@ public class AckTest extends TestCase
// we increment the reference here since we are not delivering the messaging to any queues, which is where
// the reference is normally incremented. The test is easier to construct if we have direct access to the
// subscription
- msg.incrementReference();
- msg.routingComplete(_messageStore, _storeContext, factory);
+ ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>();
+ qs.add(_queue);
+ msg.enqueue(qs);
+ msg.routingComplete(_messageStore, factory);
+ if(msg.allContentReceived())
+ {
+ msg.deliverToQueues();
+ }
// we manually send the message to the subscription
- _subscription.send(new QueueEntry(_queue,msg), _queue);
+ //_subscription.send(new QueueEntry(_queue,msg), _queue);
}
}
@@ -155,16 +168,13 @@ public class AckTest extends TestCase
*/
public void testAckChannelAssociationTest() throws AMQException
{
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true, null, false, new LimitlessCreditManager());
final int msgCount = 10;
publishMessages(msgCount, true);
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
assertTrue(map.size() == msgCount);
assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount);
-
- //DTX
- // assertTrue(_messageStore.getNumberStoredMessages() == msgCount);
Set<Long> deliveryTagSet = map.getDeliveryTags();
int i = 1;
@@ -172,15 +182,12 @@ public class AckTest extends TestCase
{
assertTrue(deliveryTag == i);
i++;
- UnacknowledgedMessage unackedMsg = map.get(deliveryTag);
+ QueueEntry unackedMsg = map.get(deliveryTag);
assertTrue(unackedMsg.getQueue() == _queue);
}
assertTrue(map.size() == msgCount);
assertTrue(_messageStore.getMessageMetaDataMap().size() == msgCount);
-
- //DTX
-// assertTrue(_messageStore.getNumberStoredMessages() == msgCount);
}
/**
@@ -189,15 +196,32 @@ public class AckTest extends TestCase
public void testNoAckMode() throws AMQException
{
// false arg means no acks expected
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, false);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, false, null, false, new LimitlessCreditManager());
final int msgCount = 10;
publishMessages(msgCount);
UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
assertTrue(map.size() == 0);
assertTrue(_messageStore.getMessageMetaDataMap().size() == 0);
- //DTX MessageStore
-// assertTrue(_messageStore.getNumberStoredMessages() == 0);
+ assertTrue(_messageStore.getContentBodyMap().size() == 0);
+
+ }
+
+ /**
+ * Tests that in no-ack mode no messages are retained
+ */
+ public void testPersistentNoAckMode() throws AMQException
+ {
+ // false arg means no acks expected
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, false,null,false, new LimitlessCreditManager());
+ final int msgCount = 10;
+ publishMessages(msgCount, true);
+
+ UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap();
+ assertTrue(map.size() == 0);
+ assertTrue(_messageStore.getMessageMetaDataMap().size() == 0);
+ assertTrue(_messageStore.getContentBodyMap().size() == 0);
+
}
/**
@@ -206,7 +230,7 @@ public class AckTest extends TestCase
*/
public void testSingleAckReceivedTest() throws AMQException
{
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
final int msgCount = 10;
publishMessages(msgCount);
@@ -219,7 +243,7 @@ public class AckTest extends TestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i);
- UnacknowledgedMessage unackedMsg = map.get(deliveryTag);
+ QueueEntry unackedMsg = map.get(deliveryTag);
assertTrue(unackedMsg.getQueue() == _queue);
// 5 is the delivery tag of the message that *should* be removed
if (++i == 5)
@@ -235,7 +259,7 @@ public class AckTest extends TestCase
*/
public void testMultiAckReceivedTest() throws AMQException
{
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
final int msgCount = 10;
publishMessages(msgCount);
@@ -248,7 +272,7 @@ public class AckTest extends TestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i + 5);
- UnacknowledgedMessage unackedMsg = map.get(deliveryTag);
+ QueueEntry unackedMsg = map.get(deliveryTag);
assertTrue(unackedMsg.getQueue() == _queue);
++i;
}
@@ -259,7 +283,7 @@ public class AckTest extends TestCase
*/
public void testMultiAckAllReceivedTest() throws AMQException
{
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
final int msgCount = 10;
publishMessages(msgCount);
@@ -272,18 +296,44 @@ public class AckTest extends TestCase
for (long deliveryTag : deliveryTagSet)
{
assertTrue(deliveryTag == i + 5);
- UnacknowledgedMessage unackedMsg = map.get(deliveryTag);
+ QueueEntry unackedMsg = map.get(deliveryTag);
assertTrue(unackedMsg.getQueue() == _queue);
++i;
}
}
+ /**
+ * A regression fixing QPID-1136 showed this up
+ *
+ * @throws Exception
+ */
+ public void testMessageDequeueRestoresCreditTest() throws Exception
+ {
+ // Send 10 messages
+ Pre0_10CreditManager creditManager = new Pre0_10CreditManager(0l, 1);
+
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession,
+ DEFAULT_CONSUMER_TAG, true, null, false, creditManager);
+ final int msgCount = 1;
+ publishMessages(msgCount);
+
+ _queue.deliverAsync(_subscription);
+
+ _channel.acknowledgeMessage(1, false);
+
+ // Check credit available
+ assertTrue("No credit available", creditManager.hasCredit());
+
+ }
+
+
+/*
public void testPrefetchHighLow() throws AMQException
{
int lowMark = 5;
int highMark = 10;
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
_channel.setPrefetchLowMarkCount(lowMark);
_channel.setPrefetchHighMarkCount(highMark);
@@ -332,10 +382,12 @@ public class AckTest extends TestCase
assertTrue(map.size() == 0);
}
+*/
+/*
public void testPrefetch() throws AMQException
{
- _subscription = new SubscriptionImpl(5, _protocolSession, DEFAULT_CONSUMER_TAG, true);
- _channel.setPrefetchCount(5);
+ _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager());
+ _channel.setMessageCredit(5);
assertTrue(_channel.getPrefetchCount() == 5);
@@ -360,6 +412,7 @@ public class AckTest extends TestCase
assertTrue(map.size() == 0);
}
+*/
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(AckTest.class);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/ConcurrencyTestDisabled.java b/java/systests/src/main/java/org/apache/qpid/server/queue/ConcurrencyTestDisabled.java
deleted file mode 100644
index 4f92cc94b7..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/ConcurrencyTestDisabled.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.handler.OnCurrentThreadExecutor;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import java.util.*;
-import java.util.concurrent.Executor;
-
-/**
- * Tests delivery in the face of concurrent incoming _messages, subscription alterations
- * and attempts to asynchronously process queued _messages.
- */
-public class ConcurrencyTestDisabled extends MessageTestHelper
-{
- private final Random random = new Random();
-
- private final int numMessages = 10;
-
- private final List<SubscriptionTestHelper> _subscribers = new ArrayList<SubscriptionTestHelper>();
- private final Set<Subscription> _active = new HashSet<Subscription>();
- private final List<QueueEntry> _messages = new ArrayList<QueueEntry>();
- private int next = 0;//index to next message to send
- private final List<QueueEntry> _received = Collections.synchronizedList(new ArrayList<QueueEntry>());
- private final Executor _executor = new OnCurrentThreadExecutor();
- private final List<Thread> _threads = new ArrayList<Thread>();
-
- private final SubscriptionSet _subscriptionMgr = new SubscriptionSet();
- private final DeliveryManager _deliveryMgr;
-
- private boolean isComplete;
- private boolean failed;
- private VirtualHost _virtualHost;
-
- public ConcurrencyTestDisabled() throws Exception
- {
-
- IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance();
- _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test");
- _deliveryMgr = new ConcurrentSelectorDeliveryManager(_subscriptionMgr, new AMQQueue(new AMQShortString("myQ"), false, new AMQShortString("guest"), false,
- _virtualHost));
- }
-
- public void testConcurrent1() throws InterruptedException, AMQException
- {
- initSubscriptions(10);
- initMessages(numMessages);
- initThreads(1, 4, 4, 4);
- doRun();
- check();
- }
-
- public void testConcurrent2() throws InterruptedException, AMQException
- {
- initSubscriptions(10);
- initMessages(numMessages);
- initThreads(4, 2, 2, 2);
- doRun();
- check();
- }
-
- void check()
- {
- assertFalse("Failed", failed);
-
- _deliveryMgr.processAsync(_executor);
-
- assertEquals("Did not recieve the correct number of messages", _messages.size(), _received.size());
- for(int i = 0; i < _messages.size(); i++)
- {
- assertEquals("Wrong message at " + i, _messages.get(i), _received.get(i));
- }
- }
-
- void initSubscriptions(int subscriptions)
- {
- for(int i = 0; i < subscriptions; i++)
- {
- _subscribers.add(new SubscriptionTestHelper("Subscriber" + i, _received));
- }
- }
-
- void initMessages(int messages) throws AMQException
- {
- for(int i = 0; i < messages; i++)
- {
- _messages.add(message());
- }
- }
-
- void initThreads(int senders, int subscribers, int suspenders, int processors)
- {
- addThreads(senders, senders == 1 ? new Sender() : new OrderedSender());
- addThreads(subscribers, new Subscriber());
- addThreads(suspenders, new Suspender());
- addThreads(processors, new Processor());
- }
-
- void addThreads(int count, Runnable runner)
- {
- for(int i = 0; i < count; i++)
- {
- _threads.add(new Thread(runner, runner.toString()));
- }
- }
-
- void doRun() throws InterruptedException
- {
- for(Thread t : _threads)
- {
- t.start();
- }
-
- for(Thread t : _threads)
- {
- t.join();
- }
- }
-
- private void toggle(Subscription s)
- {
- synchronized (_active)
- {
- if (_active.contains(s))
- {
- _active.remove(s);
- Subscription result = _subscriptionMgr.removeSubscriber(s);
- assertTrue("Removed subscription " + result + " but trying to remove subscription " + s,
- result != null && result.equals(s));
- }
- else
- {
- _active.add(s);
- _subscriptionMgr.addSubscriber(s);
- }
- }
- }
-
- private QueueEntry nextMessage()
- {
- synchronized (_messages)
- {
- if (next < _messages.size())
- {
- return _messages.get(next++);
- }
- else
- {
- if (!_deliveryMgr.hasQueuedMessages()) {
- isComplete = true;
- }
- return null;
- }
- }
- }
-
- private boolean randomBoolean()
- {
- return random.nextBoolean();
- }
-
- private SubscriptionTestHelper randomSubscriber()
- {
- return _subscribers.get(random.nextInt(_subscribers.size()));
- }
-
- private class Sender extends Runner
- {
- void doRun() throws Throwable
- {
- QueueEntry msg = nextMessage();
- if (msg != null)
- {
- _deliveryMgr.deliver(null, new AMQShortString(toString()), msg, false);
- }
- }
- }
-
- private class OrderedSender extends Sender
- {
- synchronized void doRun() throws Throwable
- {
- super.doRun();
- }
- }
-
- private class Suspender extends Runner
- {
- void doRun() throws Throwable
- {
- randomSubscriber().setSuspended(randomBoolean());
- }
- }
-
- private class Subscriber extends Runner
- {
- void doRun() throws Throwable
- {
- toggle(randomSubscriber());
- }
- }
-
- private class Processor extends Runner
- {
- void doRun() throws Throwable
- {
- _deliveryMgr.processAsync(_executor);
- }
- }
-
- private abstract class Runner implements Runnable
- {
- public void run()
- {
- try
- {
- while (!stop())
- {
- doRun();
- }
- }
- catch (Throwable t)
- {
- failed = true;
- t.printStackTrace();
- }
- }
-
- abstract void doRun() throws Throwable;
-
- boolean stop()
- {
- return isComplete || failed;
- }
- }
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(ConcurrencyTestDisabled.class);
- }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/DeliveryManagerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/DeliveryManagerTest.java
deleted file mode 100644
index b33259cfba..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/DeliveryManagerTest.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.server.handler.OnCurrentThreadExecutor;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-
-import junit.framework.TestSuite;
-
-abstract public class DeliveryManagerTest extends MessageTestHelper
-{
- protected final SubscriptionSet _subscriptions = new SubscriptionSet();
- protected DeliveryManager _mgr;
- protected StoreContext _storeContext = new StoreContext();
- private static final AMQShortString DEFAULT_QUEUE_NAME = new AMQShortString("Me");
-
- public DeliveryManagerTest() throws Exception
- {
- }
-
- public void testStartInQueueingMode() throws AMQException
- {
- QueueEntry[] messages = new QueueEntry[10];
- for (int i = 0; i < messages.length; i++)
- {
- messages[i] = message();
- }
- int batch = messages.length / 2;
-
- for (int i = 0; i < batch; i++)
- {
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, messages[i], false);
- }
-
- SubscriptionTestHelper s1 = new SubscriptionTestHelper("1");
- SubscriptionTestHelper s2 = new SubscriptionTestHelper("2");
- _subscriptions.addSubscriber(s1);
- _subscriptions.addSubscriber(s2);
-
- for (int i = batch; i < messages.length; i++)
- {
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, messages[i], false);
- }
-
- assertTrue(s1.getMessages().isEmpty());
- assertTrue(s2.getMessages().isEmpty());
-
- _mgr.processAsync(new OnCurrentThreadExecutor());
-
- assertEquals(messages.length / 2, s1.getMessages().size());
- assertEquals(messages.length / 2, s2.getMessages().size());
-
- for (int i = 0; i < messages.length; i++)
- {
- if (i % 2 == 0)
- {
- assertTrue(s1.getMessages().get(i / 2) == messages[i]);
- }
- else
- {
- assertTrue(s2.getMessages().get(i / 2) == messages[i]);
- }
- }
- }
-
- public void testStartInDirectMode() throws AMQException
- {
- QueueEntry[] messages = new QueueEntry[10];
- for (int i = 0; i < messages.length; i++)
- {
- messages[i] = message();
- }
- int batch = messages.length / 2;
-
- SubscriptionTestHelper s1 = new SubscriptionTestHelper("1");
- _subscriptions.addSubscriber(s1);
-
- for (int i = 0; i < batch; i++)
- {
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, messages[i], false);
- }
-
- assertEquals(batch, s1.getMessages().size());
- for (int i = 0; i < batch; i++)
- {
- assertTrue(messages[i] == s1.getMessages().get(i));
- }
- s1.getMessages().clear();
- assertEquals(0, s1.getMessages().size());
-
- s1.setSuspended(true);
- for (int i = batch; i < messages.length; i++)
- {
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, messages[i], false);
- }
-
- _mgr.processAsync(new OnCurrentThreadExecutor());
- assertEquals(0, s1.getMessages().size());
- s1.setSuspended(false);
-
- _mgr.processAsync(new OnCurrentThreadExecutor());
- assertEquals(messages.length - batch, s1.getMessages().size());
-
- for (int i = batch; i < messages.length; i++)
- {
- assertTrue(messages[i] == s1.getMessages().get(i - batch));
- }
-
- }
-
- public void testNoConsumers() throws AMQException
- {
- try
- {
- QueueEntry msg = message(true);
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, msg, false);
- msg.checkDeliveredToConsumer();
- fail("expected exception did not occur");
- }
- catch (NoConsumersException m)
- {
- // ok
- }
- catch (Exception e)
- {
- fail("expected NoConsumersException, got " + e);
- }
- }
-
- public void testNoActiveConsumers() throws AMQException
- {
- try
- {
- SubscriptionTestHelper s = new SubscriptionTestHelper("A");
- _subscriptions.addSubscriber(s);
- s.setSuspended(true);
- QueueEntry msg = message(true);
- _mgr.deliver(_storeContext, DEFAULT_QUEUE_NAME, msg, false);
- msg.checkDeliveredToConsumer();
- fail("expected exception did not occur");
- }
- catch (NoConsumersException m)
- {
- // ok
- }
- catch (Exception e)
- {
- fail("expected NoConsumersException, got " + e);
- }
- }
-
- public static junit.framework.Test suite()
- {
- TestSuite suite = new TestSuite();
- return suite;
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java
index 114c8cac32..b2a4216f8d 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/MessageTestHelper.java
@@ -24,7 +24,7 @@ import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.MemoryMessageStore;
+import org.apache.qpid.server.store.SkeletonMessageStore;
import org.apache.qpid.server.store.StoreContext;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.util.NullApplicationRegistry;
@@ -39,7 +39,7 @@ import java.util.LinkedList;
class MessageTestHelper extends TestCase
{
- private final MessageStore _messageStore = new MemoryMessageStore();
+ private final MessageStore _messageStore = new SkeletonMessageStore();
private final StoreContext _storeContext = new StoreContext();
@@ -52,12 +52,12 @@ class MessageTestHelper extends TestCase
ApplicationRegistry.initialise(new NullApplicationRegistry());
}
- QueueEntry message() throws AMQException
+ QueueEntryImpl message() throws AMQException
{
return message(false);
}
- QueueEntry message(final boolean immediate) throws AMQException
+ QueueEntryImpl message(final boolean immediate) throws AMQException
{
MessagePublishInfo publish = new MessagePublishInfo()
{
@@ -87,9 +87,16 @@ class MessageTestHelper extends TestCase
return null;
}
};
-
- return new QueueEntry(null,new AMQMessage(_messageStore.getNewMessageId(), publish, _txnContext,
- new ContentHeaderBody()));
+
+ //public AMQMessage(Long messageId, AMQMessageHandle messageHandle , TransactionalContext txnConext, MessagePublishInfo info)
+ long messageId = _messageStore.getNewMessageId();
+ final AMQMessageHandle messageHandle =
+ (new MessageHandleFactory()).createMessageHandle(messageId, _messageStore, false);
+ messageHandle.setPublishAndContentHeaderBody(new StoreContext(),publish,new ContentHeaderBody());
+ AMQMessage msg = new AMQMessage(messageHandle, _txnContext.getStoreContext(), publish);
+
+
+ return new QueueEntryImpl(null,msg, Long.MIN_VALUE);
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
index cf986e7803..99c88fac3e 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.framing.*;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.output.ProtocolOutputConverter;
@@ -28,6 +29,7 @@ import org.apache.qpid.server.output.ProtocolOutputConverterRegistry;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.transport.Sender;
import javax.security.sasl.SaslServer;
import java.util.HashMap;
@@ -117,6 +119,10 @@ public class MockProtocolSession implements AMQProtocolSession
{
}
+ public void closeConnection(int channelId, AMQConnectionException e, boolean closeIoSession) throws AMQException
+ {
+ }
+
public Object getKey()
{
return null;
@@ -215,6 +221,11 @@ public class MockProtocolSession implements AMQProtocolSession
return null; //To change body of implemented methods use File | Settings | File Templates.
}
+ public ProtocolSessionIdentifier getSessionIdentifier()
+ {
+ return null;
+ }
+
public byte getProtocolMajorVersion()
{
return getProtocolVersion().getMajorVersion();
@@ -236,4 +247,16 @@ public class MockProtocolSession implements AMQProtocolSession
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
+
+ public void setSender(Sender<java.nio.ByteBuffer> sender)
+ {
+ // FIXME AS TODO
+
+ }
+
+ public void init()
+ {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java
new file mode 100644
index 0000000000..0dbf95052f
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/PriorityTest.java
@@ -0,0 +1,176 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.server.queue;
+
+import junit.framework.TestCase;
+import junit.framework.Assert;
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+
+import javax.jms.*;
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.naming.spi.InitialContextFactory;
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Test Case provided by client Non-functional Test NF101: heap exhaustion behaviour */
+public class PriorityTest extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(PriorityTest.class);
+
+
+ protected final String BROKER = "vm://:1";
+ protected final String VHOST = "/test";
+ protected final String QUEUE = "PriorityQueue";
+
+
+ private static final int MSG_COUNT = 50;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ if (usingInVMBroker())
+ {
+ TransportConnection.createVMBroker(1);
+ }
+
+
+ }
+
+ private boolean usingInVMBroker()
+ {
+ return BROKER.startsWith("vm://");
+ }
+
+ protected void tearDown() throws Exception
+ {
+ if (usingInVMBroker())
+ {
+ TransportConnection.killAllVMBrokers();
+ }
+ super.tearDown();
+ }
+
+ public void testPriority() throws JMSException, NamingException, AMQException
+ {
+ InitialContextFactory factory = new PropertiesFileInitialContextFactory();
+
+ Hashtable<String, String> env = new Hashtable<String, String>();
+
+ env.put("connectionfactory.connection", "amqp://guest:guest@PRIORITY_TEST_ID" + VHOST + "?brokerlist='" + BROKER + "'");
+ env.put("queue.queue", QUEUE);
+
+ Context context = factory.getInitialContext(env);
+
+ Connection producerConnection = ((ConnectionFactory) context.lookup("connection")).createConnection();
+
+ Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ final Map<String,Object> arguments = new HashMap<String, Object>();
+ arguments.put("x-qpid-priorities",10);
+
+ ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), true, false, false, arguments);
+
+ Queue queue = new AMQQueue("amq.direct",QUEUE);
+
+ ((AMQSession) producerSession).declareAndBind((AMQDestination)queue);
+
+
+
+
+
+
+ producerConnection.start();
+
+
+ MessageProducer producer = producerSession.createProducer(queue);
+
+
+
+
+
+ for (int msg = 0; msg < MSG_COUNT; msg++)
+ {
+ producer.setPriority(msg % 10);
+ producer.send(nextMessage(msg, false, producerSession, producer));
+ }
+
+ producer.close();
+ producerSession.close();
+ producerConnection.close();
+
+
+ Connection consumerConnection = ((ConnectionFactory) context.lookup("connection")).createConnection();
+ Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageConsumer consumer = consumerSession.createConsumer(queue);
+
+
+
+
+ consumerConnection.start();
+
+ Message received;
+ //Receive Message 0
+ StringBuilder buf = new StringBuilder();
+ int receivedCount = 0;
+ Message previous = null;
+ int messageCount = 0;
+ while((received = consumer.receive(1000))!=null)
+ {
+ messageCount++;
+ if(previous != null)
+ {
+ assertTrue("Messages arrived in unexpected order " + messageCount + " " + previous.getIntProperty("msg") + " " + received.getIntProperty("msg") + " " + previous.getJMSPriority() + " " + received.getJMSPriority(), (previous.getJMSPriority() > received.getJMSPriority()) || ((previous.getJMSPriority() == received.getJMSPriority()) && previous.getIntProperty("msg") < received.getIntProperty("msg")) );
+ }
+
+ previous = received;
+ receivedCount++;
+ }
+
+ assertEquals("Incorrect number of message received", 50, receivedCount);
+
+ producerSession.close();
+ producer.close();
+
+ }
+
+ private Message nextMessage(int msg, boolean first, Session producerSession, MessageProducer producer) throws JMSException
+ {
+ Message send = producerSession.createTextMessage("Message: " + msg);
+ send.setIntProperty("msg", msg);
+
+ return send;
+ }
+
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
index f82fec61b0..280d897852 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/QueueDepthWithSelectorTest.java
@@ -81,14 +81,6 @@ public class QueueDepthWithSelectorTest extends TestCase
System.err.println("_logger.isDebug:" + _logger.isDebugEnabled() + ":" + _logger.isEnabledFor(Level.DEBUG));
System.err.println("_logger.isTrace:" + _logger.isTraceEnabled() + ":" + _logger.isEnabledFor(Level.TRACE));
- Logger csdm = Logger.getLogger(ConcurrentSelectorDeliveryManager.class);
- System.err.println("csdm.isE-Error:" + csdm.isEnabledFor(Level.ERROR));
- System.err.println("csdm.isE-Warn:" + csdm.isEnabledFor(Level.WARN));
- System.err.println("csdm.isInfo:" + csdm.isInfoEnabled() + ":" + csdm.isEnabledFor(Level.INFO));
- System.err.println("csdm.isDebug:" + csdm.isDebugEnabled() + ":" + csdm.isEnabledFor(Level.DEBUG));
- System.err.println("csdm.isTrace:" + csdm.isTraceEnabled() + ":" + csdm.isEnabledFor(Level.TRACE));
-
-
System.err.println(Logger.getRootLogger().getLoggerRepository());
if (BROKER.startsWith("vm://"))
@@ -184,9 +176,14 @@ public class QueueDepthWithSelectorTest extends TestCase
try
{
+ Thread.sleep(2000);
long queueDepth = ((AMQSession) _clientSession).getQueueDepth((AMQDestination) _context.lookup("queue"));
assertEquals("Session reports Queue depth not as expected", 0, queueDepth);
}
+ catch (InterruptedException e)
+ {
+ fail(e.getMessage());
+ }
catch (NamingException e)
{
fail(e.getMessage());
@@ -209,7 +206,7 @@ public class QueueDepthWithSelectorTest extends TestCase
}
- private void verifyAllMessagesRecevied() throws JMSException
+ private void verifyAllMessagesRecevied() throws Exception
{
boolean[] msgIdRecevied = new boolean[MSG_COUNT];
@@ -219,6 +216,8 @@ public class QueueDepthWithSelectorTest extends TestCase
_messages[i] = _consumer.receive(1000);
assertNotNull("should have received a message but didn't", _messages[i]);
}
+ long queueDepth = ((AMQSession) _clientSession).getQueueDepth((AMQDestination) _context.lookup("queue"));
+ assertEquals("Session reports Queue depth not as expected", 0, queueDepth);
//Check received messages
int msgId = 0;
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionManagerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionManagerTest.java
deleted file mode 100644
index d3ec3c11d4..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionManagerTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import junit.framework.TestCase;
-
-public class SubscriptionManagerTest extends TestCase
-{
- private final SubscriptionSet mgr = new SubscriptionSet();
-
- public void testBasicSubscriptionManagement()
- {
- assertTrue(mgr.isEmpty());
- assertFalse(mgr.hasActiveSubscribers());
- SubscriptionTestHelper s1 = new SubscriptionTestHelper("S1");
- mgr.addSubscriber(s1);
- assertFalse(mgr.isEmpty());
- assertTrue(mgr.hasActiveSubscribers());
-
- SubscriptionTestHelper s2 = new SubscriptionTestHelper("S2");
- mgr.addSubscriber(s2);
-
- s2.setSuspended(true);
- assertFalse(mgr.isEmpty());
- assertTrue(mgr.hasActiveSubscribers());
- assertTrue(s2.isSuspended());
- assertFalse(s1.isSuspended());
-
- s1.setSuspended(true);
- assertFalse(mgr.hasActiveSubscribers());
-
- mgr.removeSubscriber(new SubscriptionTestHelper("S1"));
- assertFalse(mgr.isEmpty());
- mgr.removeSubscriber(new SubscriptionTestHelper("S2"));
- assertTrue(mgr.isEmpty());
- }
-
- public void testRoundRobin()
- {
- SubscriptionTestHelper a = new SubscriptionTestHelper("A");
- SubscriptionTestHelper b = new SubscriptionTestHelper("B");
- SubscriptionTestHelper c = new SubscriptionTestHelper("C");
- SubscriptionTestHelper d = new SubscriptionTestHelper("D");
- mgr.addSubscriber(a);
- mgr.addSubscriber(b);
- mgr.addSubscriber(c);
- mgr.addSubscriber(d);
-
- for (int i = 0; i < 3; i++)
- {
- assertEquals(a, mgr.nextSubscriber(null));
- assertEquals(b, mgr.nextSubscriber(null));
- assertEquals(c, mgr.nextSubscriber(null));
- assertEquals(d, mgr.nextSubscriber(null));
- }
-
- c.setSuspended(true);
-
- for (int i = 0; i < 3; i++)
- {
- assertEquals(a, mgr.nextSubscriber(null));
- assertEquals(b, mgr.nextSubscriber(null));
- assertEquals(d, mgr.nextSubscriber(null));
- }
-
- mgr.removeSubscriber(a);
- d.setSuspended(true);
- c.setSuspended(false);
- Subscription e = new SubscriptionTestHelper("D");
- mgr.addSubscriber(e);
-
- for (int i = 0; i < 3; i++)
- {
- assertEquals(b, mgr.nextSubscriber(null));
- assertEquals(c, mgr.nextSubscriber(null));
- assertEquals(e, mgr.nextSubscriber(null));
- }
- }
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(SubscriptionManagerTest.class);
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionSetTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionSetTest.java
deleted file mode 100644
index bcf54693d3..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionSetTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import junit.framework.TestCase;
-
-public class SubscriptionSetTest extends TestCase
-{
- /**
- * A SubscriptionSet that counts the number of items scanned.
- */
- static class TestSubscriptionSet extends SubscriptionSet
- {
- private int scanned = 0;
-
- void resetScanned()
- {
- scanned = 0;
- }
-
- protected void subscriberScanned()
- {
- ++scanned;
- }
-
- int getScanned()
- {
- return scanned;
- }
- }
-
- final SubscriptionTestHelper sub1 = new SubscriptionTestHelper("1");
- final SubscriptionTestHelper sub2 = new SubscriptionTestHelper("2");
- final SubscriptionTestHelper sub3 = new SubscriptionTestHelper("3");
-
- final SubscriptionTestHelper suspendedSub1 = new SubscriptionTestHelper("sus1", true);
- final SubscriptionTestHelper suspendedSub2 = new SubscriptionTestHelper("sus2", true);
- final SubscriptionTestHelper suspendedSub3 = new SubscriptionTestHelper("sus3", true);
-
- public void testNextMessage()
- {
- SubscriptionSet ss = new SubscriptionSet();
- assertNull(ss.nextSubscriber(null));
- assertEquals(0, ss.getCurrentSubscriber());
-
- ss.addSubscriber(sub1);
- assertEquals(sub1, ss.nextSubscriber(null));
- assertEquals(1, ss.getCurrentSubscriber());
- assertEquals(sub1, ss.nextSubscriber(null));
- assertEquals(1, ss.getCurrentSubscriber());
-
- ss.addSubscriber(sub2);
- ss.addSubscriber(sub3);
-
- assertEquals(sub2, ss.nextSubscriber(null));
- assertEquals(2, ss.getCurrentSubscriber());
-
- assertEquals(sub3, ss.nextSubscriber(null));
- assertEquals(3, ss.getCurrentSubscriber());
- }
-
- public void testNextMessageWhenAllSuspended()
- {
- SubscriptionSet ss = createAllSuspendedSubscriptionSet();
- assertNull(ss.nextSubscriber(null));
- assertEquals(3, ss.getCurrentSubscriber());
-
- assertNull(ss.nextSubscriber(null));
- assertEquals(3, ss.getCurrentSubscriber());
- }
-
- private TestSubscriptionSet createAllSuspendedSubscriptionSet()
- {
- TestSubscriptionSet ss = new TestSubscriptionSet();
- ss.addSubscriber(suspendedSub1);
- ss.addSubscriber(suspendedSub2);
- ss.addSubscriber(suspendedSub3);
- return ss;
- }
-
- public void testNextMessageAfterRemove()
- {
- SubscriptionSet ss = new SubscriptionSet();
- ss.addSubscriber(suspendedSub1);
- ss.addSubscriber(suspendedSub2);
- ss.addSubscriber(sub3);
- assertEquals(sub3, ss.nextSubscriber(null));
- assertEquals(3, ss.getCurrentSubscriber());
-
- assertEquals(suspendedSub1, ss.removeSubscriber(suspendedSub1));
-
- assertEquals(sub3, ss.nextSubscriber(null)); // Current implementation handles OutOfBoundsException here.
- assertEquals(2, ss.getCurrentSubscriber());
- }
-
- public void testNextMessageOverScanning()
- {
- TestSubscriptionSet ss = new TestSubscriptionSet();
- SubscriptionTestHelper sub = new SubscriptionTestHelper("test");
- ss.addSubscriber(suspendedSub1);
- ss.addSubscriber(sub);
- ss.addSubscriber(suspendedSub3);
- assertEquals(sub, ss.nextSubscriber(null));
- assertEquals(2, ss.getCurrentSubscriber());
- assertEquals(2, ss.getScanned());
-
- ss.resetScanned();
- sub.setSuspended(true);
- assertNull(ss.nextSubscriber(null));
- assertEquals(3, ss.getCurrentSubscriber());
- // Current implementation overscans by one item here.
- assertEquals(ss.size() + 1, ss.getScanned());
- }
-
- public void testNextMessageOverscanWorstCase() {
- TestSubscriptionSet ss = createAllSuspendedSubscriptionSet();
- ss.nextSubscriber(null);
- // Scans the subscriptions twice.
- assertEquals(ss.size() * 2, ss.getScanned());
- }
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(SubscriptionSetTest.class);
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java b/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
index 1fa70a08d4..eed60a1a7c 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/SubscriptionTestHelper.java
@@ -21,6 +21,8 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.framing.AMQShortString;
import java.util.ArrayList;
import java.util.List;
@@ -54,7 +56,12 @@ public class SubscriptionTestHelper implements Subscription
return messages;
}
- public void send(QueueEntry msg, AMQQueue queue)
+ public void setQueue(AMQQueue queue)
+ {
+
+ }
+
+ public void send(QueueEntry msg)
{
messages.add(msg);
}
@@ -79,9 +86,39 @@ public class SubscriptionTestHelper implements Subscription
//no-op
}
- public Object getSendLock()
+ public void getSendLock()
+ {
+ return;
+ }
+
+ public void releaseSendLock()
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void resend(final QueueEntry entry)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void restoreCredit(final QueueEntry queueEntry)
+ {
+
+ }
+
+ public void setStateListener(final StateListener listener)
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public QueueEntry getLastSeenEntry()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean setLastSeenEntry(QueueEntry expected, QueueEntry newValue)
{
- return new Object();
+ return false; //To change body of implemented methods use File | Settings | File Templates.
}
public AMQChannel getChannel()
@@ -94,6 +131,26 @@ public class SubscriptionTestHelper implements Subscription
//no-op
}
+ public AMQShortString getConsumerTag()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public boolean isActive()
+ {
+ return false; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public AMQQueue getQueue()
+ {
+ return null;
+ }
+
+ public QueueEntry.SubscriptionAcquiredState getOwningState()
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
public void queueDeleted(AMQQueue queue)
{
}
@@ -108,6 +165,11 @@ public class SubscriptionTestHelper implements Subscription
return true;
}
+ public boolean isAutoClose()
+ {
+ return false;
+ }
+
public Queue<QueueEntry> getPreDeliveryQueue()
{
return null;
@@ -157,5 +219,4 @@ public class SubscriptionTestHelper implements Subscription
{
return key.toString();
}
-
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java
index a803bf7da5..c60748b5cb 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/TimeToLiveTest.java
@@ -30,6 +30,7 @@ import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
import org.apache.qpid.url.URLSyntaxException;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.log4j.Logger;
import javax.jms.JMSException;
@@ -82,7 +83,8 @@ public class TimeToLiveTest extends TestCase
{
if (usingInVMBroker())
{
- TransportConnection.killAllVMBrokers();
+ TransportConnection.killVMBroker(1);
+ ApplicationRegistry.remove(1);
}
super.tearDown();
}
@@ -95,7 +97,7 @@ public class TimeToLiveTest extends TestCase
env.put("connectionfactory.connection", "amqp://guest:guest@TTL_TEST_ID" + VHOST + "?brokerlist='" + BROKER + "'");
env.put("queue.queue", QUEUE);
-
+
Context context = factory.getInitialContext(env);
Queue queue = (Queue) context.lookup("queue");
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
index e39b1122cf..db29b2d5f9 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/SimpleACLTest.java
@@ -35,7 +35,6 @@ import javax.jms.*;
import javax.jms.IllegalStateException;
import java.io.File;
-
public class SimpleACLTest extends TestCase implements ConnectionListener
{
private String BROKER = "vm://:1";//"tcp://localhost:5672";
@@ -52,7 +51,7 @@ public class SimpleACLTest extends TestCase implements ConnectionListener
fail("Configuration file not found:" + defaultaclConfigFile);
}
- if (System.getProperty("QPID_HOME") == null)
+ if (System.getProperty("QPID_HOME") == null)
{
fail("QPID_HOME not set");
}
@@ -73,7 +72,7 @@ public class SimpleACLTest extends TestCase implements ConnectionListener
public String createConnectionString(String username, String password, String broker)
{
- return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + broker + "'";
+ return "amqp://" + username + ":" + password + "@clientid/test?brokerlist='" + broker + "?retries='0''";
}
public void testAccessAuthorized() throws AMQException, URLSyntaxException
@@ -113,15 +112,9 @@ public class SimpleACLTest extends TestCase implements ConnectionListener
}
catch (AMQException amqe)
{
- if (amqe.getCause().getClass() == Exception.class)
- {
- System.err.println("QPID-594 : WARNING RACE CONDITION. Unable to determine cause of Connection Failure.");
- return;
- }
- assertEquals("Linked Exception Incorrect", JMSException.class, amqe.getCause().getClass());
- Exception linked = ((JMSException) amqe.getCause()).getLinkedException();
- assertEquals("Exception was wrong type", AMQAuthenticationException.class, linked.getClass());
- assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) linked).getErrorCode().getCode());
+ Throwable cause = amqe.getCause();
+ assertEquals("Exception was wrong type", AMQAuthenticationException.class, cause.getClass());
+ assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode());
}
}
@@ -304,11 +297,6 @@ public class SimpleACLTest extends TestCase implements ConnectionListener
fail("Close is not expected to succeed.");
}
- catch (IllegalStateException ise)
- {
- System.err.println("QPID-826 : WARNING : Unable to determine cause of failure due to closure as we don't " +
- "record it for reporting after connection closed asynchronously");
- }
catch (JMSException e)
{
Throwable cause = e.getLinkedException();
@@ -567,15 +555,10 @@ public class SimpleACLTest extends TestCase implements ConnectionListener
fail("Close is not expected to succeed.");
}
- catch (IllegalStateException ise)
- {
- System.err.println("QPID-826 : WARNING : Unable to determine cause of failure due to closure as we don't " +
- "record it for reporting after connection closed asynchronously");
- }
catch (JMSException e)
{
Throwable cause = e.getLinkedException();
- cause.printStackTrace();
+
assertEquals("Incorrect exception", AMQAuthenticationException.class, cause.getClass());
assertEquals("Incorrect error code thrown", 403, ((AMQAuthenticationException) cause).getErrorCode().getCode());
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java
index 6ffa3e0e02..f08a15a8a7 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/SkeletonMessageStore.java
@@ -22,12 +22,11 @@ package org.apache.qpid.server.store;
import org.apache.commons.configuration.Configuration;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.MessageMetaData;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.exchange.Exchange;
@@ -81,6 +80,10 @@ public class SkeletonMessageStore implements MessageStore
public void createQueue(AMQQueue queue) throws AMQException
{
+ }
+
+ public void createQueue(AMQQueue queue, FieldTable arguments) throws AMQException
+ {
}
public void beginTran(StoreContext s) throws AMQException
@@ -130,17 +133,22 @@ public class SkeletonMessageStore implements MessageStore
return null;
}
- public void removeQueue(AMQShortString name) throws AMQException
+ public boolean isPersistent()
+ {
+ return false;
+ }
+
+ public void removeQueue(final AMQQueue queue) throws AMQException
{
}
- public void enqueueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void enqueueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
}
- public void dequeueMessage(StoreContext context, AMQShortString name, Long messageId) throws AMQException
+ public void dequeueMessage(StoreContext context, final AMQQueue queue, Long messageId) throws AMQException
{
}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
index 79d428fee8..4e48435962 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/TestMemoryMessageStore.java
@@ -31,9 +31,9 @@ import java.util.List;
/**
* Adds some extra methods to the memory message store for testing purposes.
*/
-public class TestableMemoryMessageStore extends MemoryMessageStore
+public class TestMemoryMessageStore extends MemoryMessageStore
{
- public TestableMemoryMessageStore()
+ public TestMemoryMessageStore()
{
_metaDataMap = new ConcurrentHashMap<Long, MessageMetaData>();
_contentBodyMap = new ConcurrentHashMap<Long, List<ContentChunk>>();
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java b/java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java
index c7984d5d33..2346660d25 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/TestReferenceCounting.java
@@ -28,21 +28,22 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.queue.AMQMessage;
import org.apache.qpid.server.queue.MessageHandleFactory;
-import org.apache.qpid.server.txn.NonTransactionalContext;
+import org.apache.qpid.server.queue.AMQMessageHandle;
/**
* Tests that reference counting works correctly with AMQMessage and the message store
*/
public class TestReferenceCounting extends TestCase
{
- private TestableMemoryMessageStore _store;
+ private TestMemoryMessageStore _store;
private StoreContext _storeContext = new StoreContext();
+
protected void setUp() throws Exception
{
super.setUp();
- _store = new TestableMemoryMessageStore();
+ _store = new TestMemoryMessageStore();
}
/**
@@ -50,7 +51,7 @@ public class TestReferenceCounting extends TestCase
*/
public void testMessageGetsRemoved() throws AMQException
{
- createPersistentContentHeader();
+ ContentHeaderBody chb = createPersistentContentHeader();
MessagePublishInfo info = new MessagePublishInfo()
{
@@ -81,16 +82,22 @@ public class TestReferenceCounting extends TestCase
}
};
- AMQMessage message = new AMQMessage(_store.getNewMessageId(), info,
- new NonTransactionalContext(_store, _storeContext, null, null),
- createPersistentContentHeader());
+
+ final long messageId = _store.getNewMessageId();
+ AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true);
+ messageHandle.setPublishAndContentHeaderBody(_storeContext,info, chb);
+ AMQMessage message = new AMQMessage(messageHandle,
+ _storeContext,info);
+
message = message.takeReference();
// we call routing complete to set up the handle
- message.routingComplete(_store, _storeContext, new MessageHandleFactory());
- assertTrue(_store.getMessageMetaDataMap().size() == 1);
+ // message.routingComplete(_store, _storeContext, new MessageHandleFactory());
+
+
+ assertEquals(1, _store.getMessageMetaDataMap().size());
message.decrementReference(_storeContext);
- assertTrue(_store.getMessageMetaDataMap().size() == 0);
+ assertEquals(1, _store.getMessageMetaDataMap().size());
}
private ContentHeaderBody createPersistentContentHeader()
@@ -134,18 +141,25 @@ public class TestReferenceCounting extends TestCase
}
};
- AMQMessage message = new AMQMessage(_store.getNewMessageId(),
- info,
- new NonTransactionalContext(_store, _storeContext, null, null),
- createPersistentContentHeader());
+ final Long messageId = _store.getNewMessageId();
+ final ContentHeaderBody chb = createPersistentContentHeader();
+ AMQMessageHandle messageHandle = (new MessageHandleFactory()).createMessageHandle(messageId, _store, true);
+ messageHandle.setPublishAndContentHeaderBody(_storeContext,info,chb);
+ AMQMessage message = new AMQMessage(messageHandle,
+ _storeContext,
+ info);
+
message = message.takeReference();
// we call routing complete to set up the handle
- message.routingComplete(_store, _storeContext, new MessageHandleFactory());
- assertTrue(_store.getMessageMetaDataMap().size() == 1);
+ // message.routingComplete(_store, _storeContext, new MessageHandleFactory());
+
+
+
+ assertEquals(1, _store.getMessageMetaDataMap().size());
message = message.takeReference();
message.decrementReference(_storeContext);
- assertTrue(_store.getMessageMetaDataMap().size() == 1);
+ assertEquals(1, _store.getMessageMetaDataMap().size());
}
public static junit.framework.Test suite()
diff --git a/java/systests/src/main/java/org/apache/qpid/server/txn/TxnBufferTest.java b/java/systests/src/main/java/org/apache/qpid/server/txn/TxnBufferTest.java
index b34f28b1a8..84d3d313d1 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/txn/TxnBufferTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/txn/TxnBufferTest.java
@@ -23,7 +23,7 @@ package org.apache.qpid.server.txn;
import junit.framework.TestCase;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TestableMemoryMessageStore;
+import org.apache.qpid.server.store.TestMemoryMessageStore;
import org.apache.qpid.server.store.StoreContext;
import java.util.LinkedList;
@@ -194,7 +194,7 @@ public class TxnBufferTest extends TestCase
}
}
- class MockStore extends TestableMemoryMessageStore
+ class MockStore extends TestMemoryMessageStore
{
final Object BEGIN = "BEGIN";
final Object ABORT = "ABORT";
diff --git a/java/systests/src/main/java/org/apache/qpid/test/VMTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/VMTestCase.java
deleted file mode 100644
index dcdfb11618..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/VMTestCase.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test;
-
-import junit.framework.TestCase;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.AMQException;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.JMSException;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.spi.InitialContextFactory;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.HashMap;
-
-public class VMTestCase extends TestCase
-{
- protected long RECEIVE_TIMEOUT = 1000l; // 1 sec
- protected long CLOSE_TIMEOUT = 10000l; // 10 secs
-
- protected Context _context;
- protected String _clientID;
- protected String _virtualhost;
- protected String _brokerlist;
-
- protected final Map<String, String> _connections = new HashMap<String, String>();
- protected final Map<String, String> _queues = new HashMap<String, String>();
- protected final Map<String, String> _topics = new HashMap<String, String>();
-
- protected void setUp() throws Exception
- {
- super.setUp();
- try
- {
- TransportConnection.createVMBroker(1);
- }
- catch (Exception e)
- {
- fail("Unable to create broker: " + e);
- }
-
- InitialContextFactory factory = new PropertiesFileInitialContextFactory();
-
- Hashtable<String, String> env = new Hashtable<String, String>();
-
- if (_clientID == null)
- {
- _clientID = this.getClass().getName();
- }
-
- if (_virtualhost == null)
- {
- _virtualhost = "/test";
- }
-
- if (_brokerlist == null)
- {
- _brokerlist = "vm://:1";
- }
-
- env.put("connectionfactory.connection", "amqp://guest:guest@" + _clientID + _virtualhost + "?brokerlist='"
- + _brokerlist + "'");
-
- for (Map.Entry<String, String> c : _connections.entrySet())
- {
- env.put("connectionfactory." + c.getKey(), c.getValue());
- }
-
- _queues.put("queue", "queue");
-
- for (Map.Entry<String, String> q : _queues.entrySet())
- {
- env.put("queue." + q.getKey(), q.getValue());
- }
-
- _topics.put("topic", "topic");
-
- for (Map.Entry<String, String> t : _topics.entrySet())
- {
- env.put("topic." + t.getKey(), t.getValue());
- }
-
- _context = factory.getInitialContext(env);
- }
-
- protected void tearDown() throws Exception
- {
- //Disabled
-// checkQueuesClean();
-
- TransportConnection.killVMBroker(1);
- ApplicationRegistry.remove(1);
-
- super.tearDown();
- }
-
- private void checkQueuesClean() throws NamingException, JMSException
- {
- Connection connection = ((ConnectionFactory) _context.lookup("connection")).createConnection();
-
- Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- connection.start();
-
- Iterator<String> queueNames = new HashSet<String>(_queues.values()).iterator();
-
- assertTrue("QueueNames doesn't have next", queueNames.hasNext());
-
- while (queueNames.hasNext())
- {
- Queue queue = session.createQueue(queueNames.next());
-
- //Validate that the queue are reporting empty.
- long queueDepth = 0;
- try
- {
- queueDepth = ((AMQSession) session).getQueueDepth((AMQDestination) queue);
- }
- catch (AMQException e)
- {
- //ignore
- }
-
- assertEquals("Session reports Queue depth not as expected", 0, queueDepth);
- }
-
- connection.close();
- }
-
- public int getMessageCount(String queueName)
- {
- return ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(_virtualhost.substring(1))
- .getQueueRegistry().getQueue(new AMQShortString(queueName)).getMessageCount();
- }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
index 7b6d6eadba..25b9b0ba14 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/CancelTest.java
@@ -22,7 +22,7 @@
package org.apache.qpid.test.client;
import org.apache.log4j.Logger;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
index 57370f490f..d1bcaa1bb8 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/DupsOkTest.java
@@ -1,7 +1,6 @@
package org.apache.qpid.test.client;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
@@ -53,6 +52,10 @@ public class DupsOkTest extends QpidTestCase
_queue = (Queue) getInitialContext().lookup("queue");
+ //Declare the queue
+ Connection consumerConnection = getConnection();
+ consumerConnection.createSession(false,Session.AUTO_ACKNOWLEDGE).createConsumer(_queue).close();
+
//Create Producer put some messages on the queue
Connection producerConnection = getConnection();
@@ -84,12 +87,14 @@ public class DupsOkTest extends QpidTestCase
//Create Client
Connection clientConnection = getConnection();
- clientConnection.start();
-
final Session clientSession = clientConnection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
MessageConsumer consumer = clientSession.createConsumer(_queue);
+ assertEquals("The queue should have msgs at start", MSG_COUNT, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue));
+
+ clientConnection.start();
+
consumer.setMessageListener(new MessageListener()
{
int _msgCount = 0;
@@ -110,13 +115,10 @@ public class DupsOkTest extends QpidTestCase
{
try
{
- long remainingMessages = ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue);
- fail("The queue should have 0 msgs left, seen " + _msgCount + " messages, left: "
- + remainingMessages);
- }
- catch (AMQException e)
- {
- fail("Got AMQException" + e.getMessage());
+ if(_msgCount != MSG_COUNT)
+ {
+ assertEquals("Wrong number of messages seen.", MSG_COUNT, _msgCount);
+ }
}
finally
{
@@ -124,7 +126,6 @@ public class DupsOkTest extends QpidTestCase
_awaitCompletion.countDown();
}
}
-
}
catch (JMSException e)
{
@@ -140,14 +141,24 @@ public class DupsOkTest extends QpidTestCase
try
{
- _awaitCompletion.await(60, TimeUnit.SECONDS);
+ if (!_awaitCompletion.await(120, TimeUnit.SECONDS))
+ {
+ fail("Test did not complete in 120 seconds");
+ }
}
catch (InterruptedException e)
{
fail("Unable to wait for test completion");
throw e;
}
+
+ //Close consumer to give broker time to process in bound Acks. As The main thread will be released while
+ // before the dispatcher has sent the ack back to the broker.
+ consumer.close();
+
assertEquals("The queue should have 0 msgs left", 0, ((AMQSession) clientSession).getQueueDepth((AMQDestination) _queue));
+
+ clientConnection.close();
}
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/FlowControlTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/FlowControlTest.java
new file mode 100644
index 0000000000..94096e412d
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/FlowControlTest.java
@@ -0,0 +1,211 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*
+*/
+package org.apache.qpid.test.client;
+
+import org.apache.qpid.client.AMQSession_0_8;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.log4j.Logger;
+
+import javax.jms.*;
+
+public class FlowControlTest extends QpidTestCase
+{
+ private static final Logger _logger = Logger.getLogger(FlowControlTest.class);
+
+ private Connection _clientConnection;
+ private Session _clientSession;
+ private Queue _queue;
+
+ /**
+ * Simply
+ *
+ * @throws Exception
+ */
+ public void testBasicBytesFlowControl() throws Exception
+ {
+ _queue = (Queue) getInitialContext().lookup("queue");
+
+ //Create Client
+ _clientConnection = getConnection();
+
+ _clientConnection.start();
+
+ _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ //Ensure _queue is created
+ _clientSession.createConsumer(_queue).close();
+
+ Connection producerConnection = getConnection();
+
+ producerConnection.start();
+
+ Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(_queue);
+
+ BytesMessage m1 = producerSession.createBytesMessage();
+ m1.writeBytes(new byte[128]);
+ m1.setIntProperty("msg", 1);
+ producer.send(m1);
+ BytesMessage m2 = producerSession.createBytesMessage();
+ m2.writeBytes(new byte[128]);
+ m2.setIntProperty("msg", 2);
+ producer.send(m2);
+ BytesMessage m3 = producerSession.createBytesMessage();
+ m3.writeBytes(new byte[256]);
+ m3.setIntProperty("msg", 3);
+ producer.send(m3);
+
+ producer.close();
+ producerSession.close();
+ producerConnection.close();
+
+ Connection consumerConnection = getConnection();
+ Session consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ ((AMQSession_0_8) consumerSession).setPrefecthLimits(0, 256);
+ MessageConsumer recv = consumerSession.createConsumer(_queue);
+ consumerConnection.start();
+
+ Message r1 = recv.receive(RECEIVE_TIMEOUT);
+ assertNotNull("First message not received", r1);
+ assertEquals("Messages in wrong order", 1, r1.getIntProperty("msg"));
+
+ Message r2 = recv.receive(RECEIVE_TIMEOUT);
+ assertNotNull("Second message not received", r2);
+ assertEquals("Messages in wrong order", 2, r2.getIntProperty("msg"));
+
+ Message r3 = recv.receiveNoWait();
+ assertNull("Third message incorrectly delivered", r3);
+
+ r1.acknowledge();
+
+ r3 = recv.receiveNoWait();
+ assertNull("Third message incorrectly delivered", r3);
+
+ r2.acknowledge();
+
+ r3 = recv.receive(RECEIVE_TIMEOUT);
+ assertNotNull("Third message not received", r3);
+ assertEquals("Messages in wrong order", 3, r3.getIntProperty("msg"));
+
+ r3.acknowledge();
+ recv.close();
+ consumerSession.close();
+ consumerConnection.close();
+
+ }
+
+ public void testTwoConsumersBytesFlowControl() throws Exception
+ {
+ _queue = (Queue) getInitialContext().lookup("queue");
+
+ //Create Client
+ _clientConnection = getConnection();
+
+ _clientConnection.start();
+
+ _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ //Ensure _queue is created
+ _clientSession.createConsumer(_queue).close();
+
+ Connection producerConnection = getConnection();
+
+ producerConnection.start();
+
+ Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(_queue);
+
+ BytesMessage m1 = producerSession.createBytesMessage();
+ m1.writeBytes(new byte[128]);
+ m1.setIntProperty("msg", 1);
+ producer.send(m1);
+ BytesMessage m2 = producerSession.createBytesMessage();
+ m2.writeBytes(new byte[256]);
+ m2.setIntProperty("msg", 2);
+ producer.send(m2);
+ BytesMessage m3 = producerSession.createBytesMessage();
+ m3.writeBytes(new byte[128]);
+ m3.setIntProperty("msg", 3);
+ producer.send(m3);
+
+ producer.close();
+ producerSession.close();
+ producerConnection.close();
+
+ Connection consumerConnection = getConnection();
+ Session consumerSession1 = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ ((AMQSession_0_8) consumerSession1).setPrefecthLimits(0, 256);
+ MessageConsumer recv1 = consumerSession1.createConsumer(_queue);
+
+ consumerConnection.start();
+
+ Message r1 = recv1.receive(RECEIVE_TIMEOUT);
+ assertNotNull("First message not received", r1);
+ assertEquals("Messages in wrong order", 1, r1.getIntProperty("msg"));
+
+ Message r2 = recv1.receiveNoWait();
+ assertNull("Second message incorrectly delivered", r2);
+
+ Session consumerSession2 = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ ((AMQSession_0_8) consumerSession2).setPrefecthLimits(0, 256);
+ MessageConsumer recv2 = consumerSession2.createConsumer(_queue);
+
+ r2 = recv2.receive(100000L);//RECEIVE_TIMEOUT);
+ assertNotNull("Second message not received", r2);
+ assertEquals("Messages in wrong order", 2, r2.getIntProperty("msg"));
+
+ Message r3 = recv2.receiveNoWait();
+ assertNull("Third message incorrectly delivered", r3);
+
+ r3 = recv1.receive(100000L);//RECEIVE_TIMEOUT);
+ assertNotNull("Third message not received", r3);
+ assertEquals("Messages in wrong order", 3, r3.getIntProperty("msg"));
+
+ r2.acknowledge();
+ r3.acknowledge();
+ recv1.close();
+ recv2.close();
+ consumerSession1.close();
+ consumerSession2.close();
+ consumerConnection.close();
+
+ }
+
+ public static void main(String args[]) throws Throwable
+ {
+ FlowControlTest test = new FlowControlTest();
+
+ int run = 0;
+ while (true)
+ {
+ System.err.println("Test Run:" + ++run);
+ Thread.sleep(1000);
+
+ test.startBroker();
+ test.testBasicBytesFlowControl();
+
+ Thread.sleep(1000);
+
+ test.stopBroker();
+ }
+ }
+}
+
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
index 2dbac84fc5..9f3a8f3cb4 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
@@ -24,10 +24,9 @@ import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.FailoverBaseCase;
+import org.apache.qpid.test.utils.FailoverBaseCase;
import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
@@ -112,7 +111,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
- protected void sendMessages(Connection producerConnection, int num) throws JMSException
+ protected void sendMessages(Connection producerConnection, int messageSendCount) throws JMSException
{
producerConnection.start();
@@ -123,7 +122,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
MessageProducer producer = producerSession.createProducer(_queue);
- for (int messsageID = 0; messsageID < num; messsageID++)
+ for (int messsageID = 0; messsageID < messageSendCount; messsageID++)
{
TextMessage textMsg = producerSession.createTextMessage("Message " + messsageID);
textMsg.setIntProperty(MESSAGE_ID_PROPERTY, messsageID);
@@ -133,7 +132,15 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
producerConnection.close();
}
- protected void checkQueueDepth(int depth) throws JMSException
+ /**
+ * Using the Protocol getQueueDepth method ensure that the correct number of messages are on the queue.
+ *
+ * Also uses a QueueBrowser as a second method of validating the message count on the queue.
+ *
+ * @param expectedDepth The expected Queue depth
+ * @throws JMSException on error
+ */
+ protected void checkQueueDepth(int expectedDepth) throws JMSException
{
// create QueueBrowser
@@ -144,7 +151,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
// check for messages
if (_logger.isDebugEnabled())
{
- _logger.debug("Checking for " + depth + " messages with QueueBrowser");
+ _logger.debug("Checking for " + expectedDepth + " messages with QueueBrowser");
}
//Check what the session believes the queue count to be.
@@ -158,7 +165,9 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
{
}
- assertEquals("Session reports Queue depth not as expected", depth, queueDepth);
+ assertEquals("Session reports Queue expectedDepth not as expected", expectedDepth, queueDepth);
+
+
// Browse the queue to get a second opinion
int msgCount = 0;
@@ -176,7 +185,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
// check to see if all messages found
- assertEquals("Browser did not find all messages", depth, msgCount);
+ assertEquals("Browser did not find all messages", expectedDepth, msgCount);
//Close browser
queueBrowser.close();
@@ -206,13 +215,20 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
}
-
- protected void checkMultipleGetEnum(int sentMessages, int browserCount) throws JMSException
+ /**
+ * This method checks that multiple calls to getEnumeration() on a queueBrowser provide the same behaviour.
+ *
+ * @param sentMessages The number of messages sent
+ * @param browserEnumerationCount The number of times to call getEnumeration()
+ * @throws JMSException
+ */
+ protected void checkMultipleGetEnum(int sentMessages, int browserEnumerationCount) throws JMSException
{
QueueBrowser queueBrowser = _clientSession.createBrowser(_queue);
- for (int count = 0; count < browserCount; count++)
+ for (int count = 0; count < browserEnumerationCount; count++)
{
+ _logger.info("Checking getEnumeration:" + count);
Enumeration msgs = queueBrowser.getEnumeration();
int msgCount = 0;
@@ -222,7 +238,9 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
msgs.nextElement();
msgCount++;
}
- assertEquals(msgCount, sentMessages);
+
+ // Verify that the browser can see all the messages sent.
+ assertEquals(sentMessages, msgCount);
}
try
@@ -235,22 +253,22 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
}
- protected void checkOverlappingMultipleGetEnum(int browserCount, int expectedMessages) throws JMSException
+ protected void checkOverlappingMultipleGetEnum(int expectedMessages, int browserEnumerationCount) throws JMSException
{
- checkOverlappingMultipleGetEnum(browserCount, expectedMessages, null);
+ checkOverlappingMultipleGetEnum(expectedMessages, browserEnumerationCount, null);
}
- protected void checkOverlappingMultipleGetEnum(int browserCount, int expectedMessages, String selector) throws JMSException
+ protected void checkOverlappingMultipleGetEnum(int expectedMessages, int browserEnumerationCount, String selector) throws JMSException
{
QueueBrowser queueBrowser = selector == null ?
_clientSession.createBrowser(_queue, selector) :
_clientSession.createBrowser(_queue);
- Enumeration[] msgs = new Enumeration[browserCount];
- int[] msgCount = new int[browserCount];
+ Enumeration[] msgs = new Enumeration[browserEnumerationCount];
+ int[] msgCount = new int[browserEnumerationCount];
//create Enums
- for (int count = 0; count < browserCount; count++)
+ for (int count = 0; count < browserEnumerationCount; count++)
{
msgs[count] = queueBrowser.getEnumeration();
}
@@ -258,7 +276,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
//interleave reads
for (int cnt = 0; cnt < expectedMessages; cnt++)
{
- for (int count = 0; count < browserCount; count++)
+ for (int count = 0; count < browserEnumerationCount; count++)
{
if (msgs[count].hasMoreElements())
{
@@ -269,7 +287,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
//validate all browsers get right message count.
- for (int count = 0; count < browserCount; count++)
+ for (int count = 0; count < browserEnumerationCount; count++)
{
assertEquals(msgCount[count], expectedMessages);
}
@@ -326,12 +344,12 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
checkQueueDepth(0);
}
- protected void checkQueueDepthWithSelectors(int clients, int totalMessages) throws JMSException
+ protected void checkQueueDepthWithSelectors(int totalMessages, int clients) throws JMSException
{
String selector = MESSAGE_ID_PROPERTY + " % " + clients;
- checkOverlappingMultipleGetEnum(clients, totalMessages / clients, selector);
+ checkOverlappingMultipleGetEnum(totalMessages / clients, clients, selector);
}
@@ -376,9 +394,14 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
}
+ /**
+ * This tests that multiple getEnumerations on a QueueBrowser return the required number of messages.
+ * @throws NamingException
+ * @throws JMSException
+ */
public void testMultipleGetEnum() throws NamingException, JMSException
{
- int messages = 100;
+ int messages = 10;
sendMessages(messages);
@@ -397,7 +420,7 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
checkQueueDepth(messages);
- checkOverlappingMultipleGetEnum(5, messages);
+ checkOverlappingMultipleGetEnum(messages, 5);
validate(messages);
}
@@ -413,16 +436,21 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
for (int clients = 2; clients <= 10; clients++)
{
- checkQueueDepthWithSelectors(clients, messages);
+ checkQueueDepthWithSelectors(messages, clients);
}
validate(messages);
}
+ /**
+ * Testing that a QueueBrowser doesn't actually consume messages from a broker when it fails over.
+ * @throws JMSException
+ */
public void testFailoverWithQueueBrowser() throws JMSException
{
int messages = 5;
+
sendMessages("connection1", messages);
sendMessages("connection2", messages);
@@ -476,7 +504,9 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
//Close browser
queueBrowser.close();
- //Validate all messages still on Broker 1
+ _logger.info("Closed Queue Browser, validating messages on broker.");
+
+ //Validate all messages still on Broker
validate(messages);
}
@@ -497,20 +527,4 @@ public class QueueBrowserAutoAckTest extends FailoverBaseCase
validate(messages);
}
- public void loop() throws JMSException
- {
- int run = 0;
- try
- {
- while (true)
- {
- System.err.println(run++ + ":************************************************************************");
- testQueueBrowserMsgsRemainOnQueue();
- }
- }
- catch (Exception e)
- {
- _logger.error(e, e);
- }
- }
}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
index e7d7c7eba6..bf87e8e84f 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
@@ -21,14 +21,15 @@
package org.apache.qpid.test.client.failover;
-import junit.framework.TestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.jms.BrokerDetails;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.test.utils.FailoverBaseCase;
import org.apache.log4j.Logger;
import javax.jms.Connection;
@@ -38,82 +39,66 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
+import javax.jms.Queue;
+import javax.naming.NamingException;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
-public class FailoverTest extends TestCase implements ConnectionListener
+public class FailoverTest extends FailoverBaseCase implements ConnectionListener
{
private static final Logger _logger = Logger.getLogger(FailoverTest.class);
- private static final int NUM_BROKERS = 2;
- private static final String BROKER = "amqp://guest:guest@/test?brokerlist='vm://:%d;vm://:%d'";
private static final String QUEUE = "queue";
private static final int NUM_MESSAGES = 10;
- private Connection con;
- private AMQConnectionFactory conFactory;
- private Session prodSess;
- private AMQQueue q;
- private MessageProducer prod;
- private Session conSess;
+ private Connection connnection;
+ private Session producerSession;
+ private Queue queue;
+ private MessageProducer producer;
+ private Session consumerSession;
private MessageConsumer consumer;
private static int usedBrokers = 0;
private CountDownLatch failoverComplete;
+ private static final long DEFAULT_FAILOVER_TIME = 10000L;
@Override
protected void setUp() throws Exception
{
super.setUp();
- // Create two VM brokers
- for (int i = 0; i < NUM_BROKERS; i++)
- {
- usedBrokers++;
-
- TransportConnection.createVMBroker(usedBrokers);
- }
-
- conFactory = new AMQConnectionFactory(String.format(BROKER, usedBrokers - 1, usedBrokers));
- _logger.info("Connecting on:" + conFactory.getConnectionURL());
- con = conFactory.createConnection();
- ((AMQConnection) con).setConnectionListener(this);
- con.start();
+ connnection = getConnection();
+ ((AMQConnection) connnection).setConnectionListener(this);
+ connnection.start();
failoverComplete = new CountDownLatch(1);
}
- private void init(boolean transacted, int mode) throws JMSException
+ private void init(boolean transacted, int mode) throws JMSException, NamingException
{
- prodSess = con.createSession(transacted, mode);
- q = new AMQQueue("amq.direct", QUEUE);
- prod = prodSess.createProducer(q);
- conSess = con.createSession(transacted, mode);
- consumer = conSess.createConsumer(q);
+ queue = (Queue) getInitialContext().lookup(QUEUE);
+
+ consumerSession = connnection.createSession(transacted, mode);
+ consumer = consumerSession.createConsumer(queue);
+
+ producerSession = connnection.createSession(transacted, mode);
+ producer = producerSession.createProducer(queue);
}
@Override
- protected void tearDown() throws Exception
+ public void tearDown() throws Exception
{
try
{
- con.close();
+ connnection.close();
}
catch (Exception e)
{
}
- try
- {
- TransportConnection.killAllVMBrokers();
- ApplicationRegistry.removeAll();
- }
- catch (Exception e)
- {
- fail("Unable to clean up");
- }
super.tearDown();
}
- private void consumeMessages(int toConsume) throws JMSException
+ private void consumeMessages(int toConsume, boolean transacted) throws JMSException
{
Message msg;
for (int i = 0; i < toConsume; i++)
@@ -122,40 +107,43 @@ public class FailoverTest extends TestCase implements ConnectionListener
assertNotNull("Message " + i + " was null!", msg);
assertEquals("message " + i, ((TextMessage) msg).getText());
}
+ if (transacted) {
+ consumerSession.commit();
+ }
}
- private void sendMessages(int totalMessages) throws JMSException
+ private void sendMessages(int totalMessages, boolean transacted) throws JMSException
{
for (int i = 0; i < totalMessages; i++)
{
- prod.send(prodSess.createTextMessage("message " + i));
+ producer.send(producerSession.createTextMessage("message " + i));
+ }
+ if (transacted)
+ {
+ producerSession.commit();
}
-
-// try
-// {
-// Thread.sleep(100 * totalMessages);
-// }
-// catch (InterruptedException e)
-// {
-// //evil ignoring of IE
-// }
}
public void testP2PFailover() throws Exception
{
- testP2PFailover(NUM_MESSAGES, true);
+ testP2PFailover(NUM_MESSAGES, true, false);
}
public void testP2PFailoverWithMessagesLeft() throws Exception
{
- testP2PFailover(NUM_MESSAGES, false);
+ testP2PFailover(NUM_MESSAGES, false, false);
+ }
+
+ public void testP2PFailoverTransacted() throws Exception
+ {
+ testP2PFailover(NUM_MESSAGES, true, false);
}
- private void testP2PFailover(int totalMessages, boolean consumeAll) throws JMSException
+ private void testP2PFailover(int totalMessages, boolean consumeAll, boolean transacted) throws JMSException, NamingException
{
Message msg = null;
- init(false, Session.AUTO_ACKNOWLEDGE);
- sendMessages(totalMessages);
+ init(transacted, Session.AUTO_ACKNOWLEDGE);
+ sendMessages(totalMessages, transacted);
// Consume some messages
int toConsume = totalMessages;
@@ -164,31 +152,29 @@ public class FailoverTest extends TestCase implements ConnectionListener
toConsume = totalMessages / 2;
}
- consumeMessages(toConsume);
+ consumeMessages(toConsume, transacted);
_logger.info("Failing over");
- causeFailure();
+ causeFailure(DEFAULT_FAILOVER_TIME);
msg = consumer.receive(500);
- //todo: reinstate
+
assertNull("Should not have received message from new broker!", msg);
// Check that messages still sent / received
- sendMessages(totalMessages);
- consumeMessages(totalMessages);
+ sendMessages(totalMessages, transacted);
+ consumeMessages(totalMessages, transacted);
}
- private void causeFailure()
+ private void causeFailure(long delay)
{
- _logger.info("Failover");
- TransportConnection.killVMBroker(usedBrokers - 1);
- ApplicationRegistry.remove(usedBrokers - 1);
+ failBroker();
_logger.info("Awaiting Failover completion");
try
{
- failoverComplete.await();
+ failoverComplete.await(delay, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e)
{
@@ -199,12 +185,11 @@ public class FailoverTest extends TestCase implements ConnectionListener
public void testClientAckFailover() throws Exception
{
init(false, Session.CLIENT_ACKNOWLEDGE);
- sendMessages(1);
+ sendMessages(1, false);
Message msg = consumer.receive();
assertNotNull("Expected msgs not received", msg);
-
- causeFailure();
+ causeFailure(DEFAULT_FAILOVER_TIME);
Exception failure = null;
try
@@ -218,18 +203,41 @@ public class FailoverTest extends TestCase implements ConnectionListener
assertNotNull("Exception should be thrown", failure);
}
- // This test disabled so that it doesn't add 4 minnutes to the length of time it takes to run, which would be lame
- public void txest4MinuteFailover() throws Exception
+ /**
+ * The client used to have a fixed timeout of 4 minutes after which failover would no longer work.
+ * Check that this code has not regressed
+ *
+ * @throws Exception if something unexpected occurs in the test.
+ */
+ public void test4MinuteFailover() throws Exception
{
- conFactory = new AMQConnectionFactory("amqp://guest:guest@/test?brokerlist='vm://:"+(usedBrokers-1)+"?connectdelay='60000'&retries='2''");
- _logger.info("Connecting on:" + conFactory.getConnectionURL());
- con = conFactory.createConnection();
- ((AMQConnection) con).setConnectionListener(this);
- con.start();
-
- long failTime = System.currentTimeMillis() + 60000;
- causeFailure();
- assertTrue("Failover did not take long enough", System.currentTimeMillis() > failTime);
+ ConnectionURL connectionURL = getConnectionFactory().getConnectionURL();
+
+ int RETRIES = 4;
+ int DELAY = 60000;
+
+ //Set up a long delay on and large number of retries
+ BrokerDetails details = connectionURL.getBrokerDetails(1);
+ details.setProperty(BrokerDetails.OPTIONS_RETRY, String.valueOf(RETRIES));
+ details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, String.valueOf(DELAY));
+
+ connnection = new AMQConnection(connectionURL, null);
+
+ ((AMQConnection) connnection).setConnectionListener(this);
+
+ //Start the connection
+ connnection.start();
+
+ long FAILOVER_DELAY = (RETRIES * DELAY);
+
+ // Use Nano seconds as it is more accurate for comparision.
+ long failTime = System.nanoTime() + FAILOVER_DELAY * 1000000;
+
+ //Fail the first broker
+ causeFailure(FAILOVER_DELAY + DEFAULT_FAILOVER_TIME);
+
+ //Reconnection should occur
+ assertTrue("Failover did not take long enough", System.nanoTime() > failTime);
}
public void bytesSent(long count)
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/message/MessageToStringTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/message/MessageToStringTest.java
new file mode 100644
index 0000000000..1744b92d62
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/message/MessageToStringTest.java
@@ -0,0 +1,251 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.client.message;
+
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.StreamMessage;
+import javax.jms.TextMessage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.util.UUID;
+
+public class MessageToStringTest extends QpidTestCase
+{
+ private Connection _connection;
+ private Session _session;
+ private Queue _queue;
+ MessageConsumer _consumer;
+ private static final String BYTE_TEST = "MapByteTest";
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ //Create Producer put some messages on the queue
+ _connection = getConnection();
+
+ //Create Queue
+ _queue = new AMQQueue("amq.direct", "queue");
+
+ //Create Consumer
+ _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _consumer = _session.createConsumer(_queue);
+
+ _connection.start();
+ }
+
+ public void tearDown() throws Exception
+ {
+ //clean up
+ _connection.close();
+
+ super.tearDown();
+ }
+
+ public void testBytesMessage() throws JMSException
+ {
+ //Create Sample Message using UUIDs
+ UUID test = UUID.randomUUID();
+
+ BytesMessage testMessage = _session.createBytesMessage();
+
+ //Convert UUID into bytes for transit
+ byte[] testBytes = test.toString().getBytes();
+
+ testMessage.writeBytes(testBytes);
+
+ sendAndTest(testMessage, testBytes);
+ }
+
+ public void testMapMessage() throws JMSException, IOException
+ {
+ //Create Sample Message using UUIDs
+ UUID test = UUID.randomUUID();
+
+ MapMessage testMessage = _session.createMapMessage();
+
+ byte[] testBytes = convertToBytes(test);
+
+ testMessage.setBytes(BYTE_TEST, testBytes);
+
+ sendAndTest(testMessage, testBytes);
+ }
+
+ public void testObjectMessage() throws JMSException
+ {
+ MessageProducer producer = _session.createProducer(_queue);
+
+ //Create Sample Message using UUIDs
+ UUID test = UUID.randomUUID();
+
+ Message testMessage = _session.createObjectMessage(test);
+
+ sendAndTest(testMessage, test);
+ }
+
+ public void testStreamMessage() throws JMSException, IOException
+ {
+ //Create Sample Message using UUIDs
+ UUID test = UUID.randomUUID();
+
+ StreamMessage testMessage = _session.createStreamMessage();
+
+ byte[] testBytes = convertToBytes(test);
+
+ testMessage.writeBytes(testBytes);
+
+ sendAndTest(testMessage, testBytes);
+ }
+
+ public void testTextMessage() throws JMSException, IOException
+ {
+ //Create Sample Message using UUIDs
+ UUID test = UUID.randomUUID();
+
+ TextMessage testMessage = _session.createTextMessage();
+
+ String stringValue = String.valueOf(test);
+ byte[] testBytes = stringValue.getBytes();
+
+ testMessage.setText(stringValue);
+
+ sendAndTest(testMessage, testBytes);
+ }
+
+ //***************** Helpers
+
+ private void sendAndTest(Message message, Object testBytes) throws JMSException
+ {
+ MessageProducer producer = _session.createProducer(_queue);
+
+ producer.send(message);
+
+ Message receivedMessage = _consumer.receive(1000);
+
+ assertNotNull("Message was not received.", receivedMessage);
+
+ //Ensure that to calling toString doesn't error and that doing this doesn't break next tests.
+ assertNotNull("Message returned null from toString", receivedMessage.toString());
+
+ byte[] byteResults;
+ UUID result;
+
+ try
+ {
+ if (receivedMessage instanceof ObjectMessage)
+ {
+ result = (UUID) ((ObjectMessage) receivedMessage).getObject();
+ assertEquals("UUIDs were not equal", testBytes, result);
+ }
+ else
+ {
+ byteResults = getBytes(receivedMessage, ((byte[]) testBytes).length);
+ assertBytesEquals("UUIDs were not equal", (byte[]) testBytes, byteResults);
+ }
+ }
+ catch (Exception e)
+ {
+ fail(e.getMessage());
+ }
+
+ }
+
+ private void assertBytesEquals(String message, byte[] expected, byte[] actual)
+ {
+ if (expected.length == actual.length)
+ {
+ int index = 0;
+ boolean failed = false;
+ for (byte b : expected)
+ {
+ if (actual[index++] != b)
+ {
+ failed = true;
+ break;
+ }
+ }
+
+ if (!failed)
+ {
+ return;
+ }
+
+ }
+
+ fail(message);
+ }
+
+ private byte[] getBytes(Message receivedMessage, int testBytesLength) throws JMSException
+ {
+ byte[] byteResults = new byte[testBytesLength];
+
+ if (receivedMessage instanceof BytesMessage)
+ {
+ assertEquals(testBytesLength, ((BytesMessage) receivedMessage).readBytes(byteResults));
+ }
+ else if (receivedMessage instanceof StreamMessage)
+ {
+ assertEquals(testBytesLength, ((StreamMessage) receivedMessage).readBytes(byteResults));
+ }
+ else if (receivedMessage instanceof MapMessage)
+ {
+ byteResults = ((MapMessage) receivedMessage).getBytes(BYTE_TEST);
+ assertEquals(testBytesLength, byteResults.length);
+ }
+ else if (receivedMessage instanceof TextMessage)
+ {
+ byteResults = ((TextMessage) receivedMessage).getText().getBytes();
+ assertEquals(testBytesLength, byteResults.length);
+ }
+
+
+ return byteResults;
+ }
+
+ private byte[] convertToBytes(UUID test) throws IOException
+ {
+ //Convert UUID into bytes for transit
+ ObjectOutput out;
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ out = new ObjectOutputStream(bos);
+ out.writeObject(test);
+ out.close();
+
+ return bos.toByteArray();
+ }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java
index 8f85d4a356..824edd7022 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/CircuitEnd.java
@@ -33,7 +33,7 @@ import javax.jms.*;
* <tr><td> Provide a message consumer for receiving messages.
* </table>
*
- * @todo Update the {@link org.apache.qpid.util.ConversationFactory} so that it accepts these as the basic conversation
+ * @todo Update the {@link org.apache.qpid.test.utils.ConversationFactory} so that it accepts these as the basic conversation
* connection units.
*/
public interface CircuitEnd
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
index 082f3f29bd..eb51a32166 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkBaseCase.java
@@ -25,12 +25,12 @@ import org.apache.log4j.NDC;
import org.apache.qpid.test.framework.BrokerLifecycleAware;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.junit.extensions.SetupTaskAware;
import org.apache.qpid.junit.extensions.SetupTaskHandler;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
import org.apache.qpid.junit.extensions.util.TestContextProperties;
-import org.apache.qpid.testutil.QpidTestCase;
import java.util.ArrayList;
import java.util.List;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
index 41766b9fae..ec70759cf7 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
@@ -26,7 +26,7 @@ import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java
index aefeb17d59..f375eda4d1 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedcircuit/DistributedCircuitImpl.java
@@ -23,7 +23,7 @@ package org.apache.qpid.test.framework.distributedcircuit;
import org.apache.log4j.Logger;
import org.apache.qpid.test.framework.*;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.TimingController;
import org.apache.qpid.junit.extensions.TimingControllerAware;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
index 55f05ec6f2..d532109dc3 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/Coordinator.java
@@ -37,7 +37,7 @@ import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.clocksynch.UDPClockReference;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.TKTestRunner;
import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java
index d2f8ca896c..bdcfc996d6 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/DistributedTestDecorator.java
@@ -27,7 +27,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java
index d6ae390a4a..eed9b1f290 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/FanOutTestDecorator.java
@@ -30,7 +30,7 @@ import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
import org.apache.qpid.test.framework.sequencers.FanOutCircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
index 38ab66d6ae..413d5558f2 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/InteropTestDecorator.java
@@ -29,7 +29,7 @@ import org.apache.qpid.test.framework.FrameworkBaseCase;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.sequencers.CircuitFactory;
import org.apache.qpid.test.framework.sequencers.InteropCircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
@@ -47,7 +47,7 @@ import java.util.*;
*
* <p><table id="crc"><caption>CRC Card</caption>
* <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Broadcast test invitations and collect enlists. <td> {@link org.apache.qpid.util.ConversationFactory}.
+ * <tr><td> Broadcast test invitations and collect enlists. <td> {@link org.apache.qpid.test.utils.ConversationFactory}.
* <tr><td> Output test failures for clients unwilling to run the test case. <td> {@link Coordinator}
* <tr><td> Execute distributed test cases. <td> {@link FrameworkBaseCase}
* <tr><td> Fail non-participating pairings. <td> {@link OptOutTestCase}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
index 9eba36e1e9..642c690376 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
@@ -27,8 +27,8 @@ import org.apache.qpid.test.framework.MessagingTestConfigProperties;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.clocksynch.ClockSynchThread;
import org.apache.qpid.test.framework.clocksynch.UDPClockSynchronizer;
-import org.apache.qpid.util.ReflectionUtils;
-import org.apache.qpid.util.ReflectionUtilsException;
+import org.apache.qpid.test.utils.ReflectionUtils;
+import org.apache.qpid.test.utils.ReflectionUtilsException;
import org.apache.qpid.junit.extensions.SleepThrottle;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
index c7bde1ae03..bd27fc3d90 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/BaseCircuitFactory.java
@@ -24,7 +24,7 @@ import org.apache.log4j.Logger;
import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.TestClientDetails;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import java.util.LinkedList;
import java.util.List;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
index 0a48d66981..e69952918d 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/CircuitFactory.java
@@ -23,7 +23,7 @@ package org.apache.qpid.test.framework.sequencers;
import org.apache.qpid.test.framework.Assertion;
import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.TestClientDetails;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
index 7f8a821c69..8a9c48d8e7 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/FanOutCircuitFactory.java
@@ -27,7 +27,7 @@ import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
index 8604dd7800..7df80bbf10 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/framework/sequencers/InteropCircuitFactory.java
@@ -27,7 +27,7 @@ import org.apache.qpid.test.framework.Circuit;
import org.apache.qpid.test.framework.TestClientDetails;
import org.apache.qpid.test.framework.TestUtils;
import org.apache.qpid.test.framework.distributedcircuit.DistributedCircuitImpl;
-import org.apache.qpid.util.ConversationFactory;
+import org.apache.qpid.test.utils.ConversationFactory;
import org.apache.qpid.junit.extensions.util.ParsedProperties;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
index 4852cab3a6..d0814ca5fc 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/AcknowledgeTest.java
@@ -31,9 +31,7 @@ import javax.jms.Session;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
public class AcknowledgeTest extends QpidTestCase
{
@@ -63,21 +61,6 @@ public class AcknowledgeTest extends QpidTestCase
_consumerA = _consumerSession.createConsumer(_queue);
}
- @Override
- protected void tearDown() throws Exception
- {
- super.tearDown();
- try
- {
- TransportConnection.killAllVMBrokers();
- ApplicationRegistry.removeAll();
- }
- catch (Exception e)
- {
- fail("Unable to clean up");
- }
-
- }
private void sendMessages(int totalMessages) throws JMSException
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java
index 216bbedef3..7434fcbb30 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ack/RecoverTest.java
@@ -23,7 +23,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
index cf09566f30..9a7fe7c039 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java
@@ -28,8 +28,7 @@ import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSBytesMessage;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -280,9 +279,4 @@ public class BytesMessageTest extends QpidTestCase implements MessageListener
test._count = count;
test.test();
}
-
- public static junit.framework.Test suite()
- {
- return new VMBrokerSetup(new junit.framework.TestSuite(BytesMessageTest.class));
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
index e8d3497bdb..979023d4b6 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
@@ -30,8 +30,7 @@ import org.apache.qpid.client.message.JMSBytesMessage;
import org.apache.qpid.framing.AMQFrameDecodingException;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -161,9 +160,4 @@ public class FieldTableMessageTest extends QpidTestCase implements MessageListen
test._count = (argv.length > 1) ? Integer.parseInt(argv[1]) : 5;
test.test();
}
-
- public static junit.framework.Test suite()
- {
- return new VMBrokerSetup(new junit.framework.TestSuite(FieldTableMessageTest.class));
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
index 1738db7239..06f4a6464f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
@@ -23,7 +23,7 @@ package org.apache.qpid.test.unit.basic;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import javax.jms.Session;
import javax.jms.QueueSession;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
index 81171fa330..24fef48028 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java
@@ -24,7 +24,7 @@ package org.apache.qpid.test.unit.basic;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
index 2c4df682f6..390850185c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
@@ -26,7 +26,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSMapMessage;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
index 4f3fc5501d..658cf26135 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
@@ -25,7 +25,7 @@ import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java
index a385c196b2..d2965bd52a 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java
@@ -20,15 +20,13 @@
package org.apache.qpid.test.unit.basic;
import junit.framework.Assert;
-import junit.framework.TestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSObjectMessage;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -116,9 +114,14 @@ public class ObjectMessageTest extends QpidTestCase implements MessageListener
{
synchronized (received)
{
+ long endTime = System.currentTimeMillis() + 30000L;
while (received.size() < count)
{
- received.wait();
+ received.wait(30000);
+ if(received.size() < count && System.currentTimeMillis() > endTime)
+ {
+ throw new RuntimeException("Only received " + received.size() + " messages, was expecting " + count);
+ }
}
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java
index 0e7bb2208b..96a162dec3 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java
@@ -21,23 +21,25 @@
package org.apache.qpid.test.unit.basic;
import junit.framework.Assert;
-import junit.framework.TestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.message.AMQMessage;
+import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.message.JMSTextMessage;
-import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.url.BindingURL;
+import org.apache.qpid.url.AMQBindingURL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
+import javax.jms.MessageFormatException;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
@@ -47,6 +49,9 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.net.URISyntaxException;
+
+import java.lang.reflect.*;
public class PropertyValueTest extends QpidTestCase implements MessageListener
{
@@ -89,6 +94,69 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
connection.start();
}
+ private Message getTestMessage() throws Exception
+ {
+ Connection conn = getConnection();
+ Session ssn = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ return ssn.createTextMessage();
+ }
+
+ public void testGetNonexistent() throws Exception
+ {
+ Message m = getTestMessage();
+ String s = m.getStringProperty("nonexistent");
+ assertNull(s);
+ }
+
+ private static final String[] NAMES = {
+ "setBooleanProperty", "setByteProperty", "setShortProperty",
+ "setIntProperty", "setLongProperty", "setFloatProperty",
+ "setDoubleProperty", "setObjectProperty"
+ };
+
+ private static final Class[] TYPES = {
+ boolean.class, byte.class, short.class, int.class, long.class,
+ float.class, double.class, Object.class
+ };
+
+ private static final Object[] VALUES = {
+ true, (byte) 0, (short) 0, 0, (long) 0, (float) 0, (double) 0,
+ new Object()
+ };
+
+ public void testSetEmptyPropertyName() throws Exception
+ {
+ Message m = getTestMessage();
+
+ for (int i = 0; i < NAMES.length; i++)
+ {
+ Method meth = m.getClass().getMethod(NAMES[i], String.class, TYPES[i]);
+ try
+ {
+ meth.invoke(m, "", VALUES[i]);
+ fail("expected illegal argument exception");
+ }
+ catch (InvocationTargetException e)
+ {
+ assertEquals(e.getCause().getClass(), IllegalArgumentException.class);
+ }
+ }
+ }
+
+ public void testSetDisallowedClass() throws Exception
+ {
+ Message m = getTestMessage();
+ try
+ {
+ m.setObjectProperty("foo", new Object());
+ fail("expected a MessageFormatException");
+ }
+ catch (MessageFormatException e)
+ {
+ // pass
+ }
+ }
+
public void testOnce()
{
runBatch(1);
@@ -185,43 +253,6 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
m.setShortProperty("Short", (short) Short.MAX_VALUE);
m.setStringProperty("String", "Test");
- // AMQP Specific values
-
- // Timestamp
- long nano = System.nanoTime();
- m.setStringProperty("time-str", String.valueOf(nano));
- ((AMQMessage) m).setTimestampProperty(new AMQShortString("time"), nano);
-
- // Decimal
- BigDecimal bd = new BigDecimal(Integer.MAX_VALUE);
- ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal"), bd.setScale(Byte.MAX_VALUE));
-
- bd = new BigDecimal((long) Integer.MAX_VALUE + 1L);
-
- try
- {
- ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal-bad-value"), bd.setScale(Byte.MAX_VALUE));
- fail("UnsupportedOperationException should be thrown as value can't be correctly transmitted");
- }
- catch (UnsupportedOperationException uoe)
- {
- // normal path.
- }
-
- try
- {
- ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal-bad-scale"),
- bd.setScale(Byte.MAX_VALUE + 1));
- fail("UnsupportedOperationException should be thrown as scale can't be correctly transmitted");
- }
- catch (UnsupportedOperationException uoe)
- {
- // normal path.
- }
-
- // Void
- ((AMQMessage) m).setVoidProperty(new AMQShortString("void"));
-
_logger.debug("Sending Msg:" + m);
producer.send(m);
}
@@ -238,7 +269,7 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
}
}
- void check() throws JMSException
+ void check() throws JMSException, URISyntaxException
{
List<String> actual = new ArrayList<String>();
for (JMSTextMessage m : received)
@@ -261,8 +292,8 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
Assert.assertEquals("Check Priority properties are correctly transported", 8, m.getJMSPriority());
// Queue
- Assert.assertEquals("Check ReplyTo properties are correctly transported", m.getStringProperty("TempQueue"),
- m.getJMSReplyTo().toString());
+ Assert.assertEquals("Check ReplyTo properties are correctly transported", AMQDestination.createDestination(new AMQBindingURL(m.getStringProperty("TempQueue"))),
+ m.getJMSReplyTo());
Assert.assertEquals("Check Type properties are correctly transported", "Test", m.getJMSType());
@@ -273,7 +304,7 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
Assert.assertEquals("Check Long properties are correctly transported", (long) Long.MAX_VALUE,
m.getLongProperty("Long"));
Assert.assertEquals("Check String properties are correctly transported", "Test", m.getStringProperty("String"));
-
+/*
// AMQP Tests Specific values
Assert.assertEquals("Check Timestamp properties are correctly transported", m.getStringProperty("time-str"),
@@ -290,7 +321,7 @@ public class PropertyValueTest extends QpidTestCase implements MessageListener
Assert.assertTrue("Check void properties are correctly transported",
((AMQMessage) m).getPropertyHeaders().containsKey("void"));
-
+*/
//JMSXUserID
if (m.getStringProperty("JMSXUserID") != null)
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java
index 60c84f451d..66c5a5b07e 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java
@@ -27,13 +27,10 @@ import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* @author Apache Software Foundation
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ReceiveTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java
index 5711d12b9e..eec3db8c5f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ReceiveTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/ReceiveTest.java
@@ -23,15 +23,11 @@ package org.apache.qpid.test.unit.basic;
import javax.jms.MessageConsumer;
import javax.jms.Message;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
public class ReceiveTest extends QpidTestCase
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java
index 987b30ce28..c42e4c7582 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SelectorTest.java
@@ -20,15 +20,14 @@
*/
package org.apache.qpid.test.unit.basic;
-import junit.framework.TestCase;
import org.apache.qpid.AMQException;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.BasicMessageProducer;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.client.state.StateWaiter;
import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
@@ -40,8 +39,9 @@ import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
+import java.util.concurrent.CountDownLatch;
-public class SelectorTest extends QpidTestCase implements MessageListener
+public class SelectorTest extends QpidTestCase implements MessageListener
{
private static final Logger _logger = LoggerFactory.getLogger(SelectorTest.class);
@@ -51,6 +51,7 @@ public class SelectorTest extends QpidTestCase implements MessageListener
private int count;
public String _connectionString = "vm://:1";
private static final String INVALID_SELECTOR = "Cost LIKE 5";
+ CountDownLatch _responseLatch = new CountDownLatch(1);
protected void setUp() throws Exception
{
@@ -83,7 +84,7 @@ public class SelectorTest extends QpidTestCase implements MessageListener
_session.createConsumer(destination, selector).setMessageListener(this);
}
- public synchronized void test() throws Exception
+ public void test() throws Exception
{
try
{
@@ -100,7 +101,8 @@ public class SelectorTest extends QpidTestCase implements MessageListener
((BasicMessageProducer) _session.createProducer(_destination)).send(msg, DeliveryMode.NON_PERSISTENT);
_logger.info("Message sent, waiting for response...");
- wait(1000);
+
+ _responseLatch.await();
if (count > 0)
{
@@ -257,11 +259,11 @@ public class SelectorTest extends QpidTestCase implements MessageListener
}
}
- public synchronized void onMessage(Message message)
+ public void onMessage(Message message)
{
count++;
_logger.info("Got Message:" + message);
- notify();
+ _responseLatch.countDown();
}
private static String randomize(String in)
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
index 7864feb069..10320914fe 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
@@ -20,15 +20,12 @@
*/
package org.apache.qpid.test.unit.basic;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -115,9 +112,4 @@ public class SessionStartTest extends QpidTestCase implements MessageListener
test.setUp();
test.test();
}
-
- public static junit.framework.Test suite()
- {
- return new VMBrokerSetup(new junit.framework.TestSuite(SessionStartTest.class));
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
index 1453e1b014..29943161d4 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
@@ -27,7 +27,7 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSTextMessage;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
index 6f1ddebb0c..21eaad6d5b 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/close/CloseTest.java
@@ -19,18 +19,14 @@
*
*/
package org.apache.qpid.test.unit.basic.close;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.url.AMQBindingURL;
-import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
index 28782229a1..c91c27e894 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQConnectionTest.java
@@ -29,7 +29,7 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
public class AMQConnectionTest extends QpidTestCase
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
index 965c22af4a..417b9b75f0 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
@@ -28,8 +28,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* Tests for QueueReceiver and TopicSubscriber creation methods on AMQSession
@@ -106,9 +105,4 @@ public class AMQSessionTest extends QpidTestCase
_topic = null;
_session = null;
}
-
- public static junit.framework.Test suite()
- {
- return new VMBrokerSetup(new junit.framework.TestSuite(AMQSessionTest.class));
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
index 74c0098d72..b843f7c9c0 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
@@ -25,7 +25,7 @@ import junit.textui.TestRunner;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
index 45a9ca1dd6..d210f5e1a1 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java
@@ -20,17 +20,11 @@
*/
package org.apache.qpid.test.unit.client.channelclose;
-import junit.framework.TestCase;
-
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQTimeoutException;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.handler.ClientMethodDispatcherImpl;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.*;
import org.apache.qpid.jms.ConnectionListener;
@@ -49,9 +43,6 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
public class ChannelCloseTest extends QpidTestCase implements ExceptionListener, ConnectionListener
{
@@ -424,27 +415,4 @@ public class ChannelCloseTest extends QpidTestCase implements ExceptionListener,
public void failoverComplete()
{ }
- private static final class MethodDispatcherProxyHandler implements InvocationHandler
- {
- private final ClientMethodDispatcherImpl _underlyingDispatcher;
- private final ChannelCloseMethodHandlerNoCloseOk _handler = ChannelCloseMethodHandlerNoCloseOk.getInstance();
-
-
- public MethodDispatcherProxyHandler(ClientMethodDispatcherImpl dispatcher)
- {
- _underlyingDispatcher = dispatcher;
- }
-
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- {
- if(method.getName().equals("dispatchChannelClose"))
- {
- _handler.methodReceived(_underlyingDispatcher.getStateManager(),
- (ChannelCloseBody) args[0], (Integer)args[1]);
- }
- Method dispatcherMethod = _underlyingDispatcher.getClass().getMethod(method.getName(), method.getParameterTypes());
- return dispatcherMethod.invoke(_underlyingDispatcher, args);
-
- }
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java
index c3be691f2d..d4d19a34ea 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/CloseWithBlockingReceiveTest.java
@@ -20,16 +20,12 @@
*/
package org.apache.qpid.test.unit.client.channelclose;
-import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.Session;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* @author Apache Software Foundation
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
index 3ab3b0410e..b932b1d784 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionCloseTest.java
@@ -20,8 +20,8 @@
*/
package org.apache.qpid.test.unit.client.connection;
-import org.apache.qpid.testutil.QpidTestCase;
-import org.apache.qpidity.transport.util.Logger;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.transport.util.Logger;
import java.util.HashMap;
import java.util.Map;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java
index 3cef57f90d..72691f3543 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionStartTest.java
@@ -34,7 +34,7 @@ import javax.jms.TextMessage;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
public class ConnectionStartTest extends QpidTestCase
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
index f856e8c20b..a6e8b80c9c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java
@@ -23,37 +23,44 @@ package org.apache.qpid.test.unit.client.connection;
import org.apache.qpid.AMQConnectionFailureException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnresolvedAddressException;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQAuthenticationException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.jms.Session;
-import junit.framework.TestCase;
-
import javax.jms.Connection;
-import javax.jms.JMSException;
import javax.jms.QueueSession;
import javax.jms.TopicSession;
+import javax.naming.NamingException;
-public class ConnectionTest extends TestCase
+public class ConnectionTest extends QpidTestCase
{
- String _broker = "vm://:1";
String _broker_NotRunning = "vm://:2";
String _broker_BadDNS = "tcp://hg3sgaaw4lgihjs";
-
- protected void setUp() throws Exception
+ public String getBroker()
{
- super.setUp();
- TransportConnection.createVMBroker(1);
- }
+ try
+ {
+ if (getConnectionFactory().getConnectionURL().getBrokerCount() > 0)
+ {
+ return getConnectionFactory().getConnectionURL().getBrokerDetails(0).toString();
+ }
+ else
+ {
+ fail("No broker details are available.");
+ }
+ }
+ catch (NamingException e)
+ {
+ fail(e.getMessage());
+ }
- protected void tearDown() throws Exception
- {
- TransportConnection.killVMBroker(1);
+ //keep compiler happy
+ return null;
}
public void testSimpleConnection() throws Exception
@@ -61,11 +68,11 @@ public class ConnectionTest extends TestCase
AMQConnection conn = null;
try
{
- conn = new AMQConnection(_broker, "guest", "guest", "fred", "test");
+ conn = new AMQConnection(getBroker(), "guest", "guest", "fred", "test");
}
catch (Exception e)
{
- fail("Connection to " + _broker + " should succeed. Reason: " + e);
+ fail("Connection to " + getBroker() + " should succeed. Reason: " + e);
}
finally
{
@@ -73,18 +80,17 @@ public class ConnectionTest extends TestCase
}
}
-
public void testDefaultExchanges() throws Exception
{
AMQConnection conn = null;
try
{
conn = new AMQConnection("amqp://guest:guest@clientid/test?brokerlist='"
- + _broker
- + "?retries='1''&defaultQueueExchange='test.direct'"
- + "&defaultTopicExchange='test.topic'"
- + "&temporaryQueueExchange='tmp.direct'"
- + "&temporaryTopicExchange='tmp.topic'");
+ + getBroker()
+ + "?retries='1''&defaultQueueExchange='test.direct'"
+ + "&defaultTopicExchange='test.topic'"
+ + "&temporaryQueueExchange='tmp.direct'"
+ + "&temporaryTopicExchange='tmp.topic'");
QueueSession queueSession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
@@ -96,10 +102,8 @@ public class ConnectionTest extends TestCase
assertEquals(tempQueue.getExchangeName().toString(), "tmp.direct");
-
queueSession.close();
-
TopicSession topicSession = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
AMQTopic topic = (AMQTopic) topicSession.createTopic("silly.topic");
@@ -115,7 +119,7 @@ public class ConnectionTest extends TestCase
}
catch (Exception e)
{
- fail("Connection to " + _broker + " should succeed. Reason: " + e);
+ fail("Connection to " + getBroker() + " should succeed. Reason: " + e);
}
finally
{
@@ -123,26 +127,18 @@ public class ConnectionTest extends TestCase
}
}
- //See QPID-771
public void testPasswordFailureConnection() throws Exception
{
AMQConnection conn = null;
try
{
- conn = new AMQConnection("amqp://guest:rubbishpassword@clientid/test?brokerlist='" + _broker + "?retries='1''");
+ conn = new AMQConnection("amqp://guest:rubbishpassword@clientid/test?brokerlist='" + getBroker() + "?retries='0''");
fail("Connection should not be established password is wrong.");
}
- catch (AMQException amqe)
+ catch (AMQConnectionFailureException amqe)
{
- if (amqe.getCause().getClass() == Exception.class)
- {
- System.err.println("QPID-594 : WARNING RACE CONDITION. Unable to determine cause of Connection Failure.");
- return;
- }
-
- assertEquals("Exception was wrong type", JMSException.class, amqe.getCause().getClass());
- Exception linked = ((JMSException) amqe.getCause()).getLinkedException();
- assertEquals("Exception was wrong type", AMQAuthenticationException.class, linked.getClass());
+ assertNotNull("No cause set:" + amqe.getMessage(), amqe.getCause());
+ assertEquals("Exception was wrong type", AMQAuthenticationException.class, amqe.getCause().getClass());
}
finally
{
@@ -208,7 +204,7 @@ public class ConnectionTest extends TestCase
AMQConnection conn = null;
try
{
- conn = new AMQConnection("amqp://guest:guest@clientid/rubbishhost?brokerlist='" + _broker + "?retries='0''");
+ conn = new AMQConnection("amqp://guest:guest@clientid/rubbishhost?brokerlist='" + getBroker() + "?retries='0''");
fail("Connection should not be established");
}
catch (AMQException amqe)
@@ -229,7 +225,7 @@ public class ConnectionTest extends TestCase
public void testClientIdCannotBeChanged() throws Exception
{
- Connection connection = new AMQConnection(_broker, "guest", "guest",
+ Connection connection = new AMQConnection(getBroker(), "guest", "guest",
"fred", "test");
try
{
@@ -251,7 +247,7 @@ public class ConnectionTest extends TestCase
public void testClientIdIsPopulatedAutomatically() throws Exception
{
- Connection connection = new AMQConnection(_broker, "guest", "guest",
+ Connection connection = new AMQConnection(getBroker(), "guest", "guest",
null, "test");
try
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
index ccf16a0b6e..6f31f7bc65 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.test.unit.client.connection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.util.concurrent.Condition;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Client.java
index f43ccaf0ff..0be11011b4 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Client.java
@@ -24,7 +24,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java
index 29d9e5de2c..a1001a6f5d 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java
@@ -20,8 +20,7 @@
*/
package org.apache.qpid.test.unit.client.forwardall;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Service.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Service.java
index 3dc9a3ccfb..9cd8b183af 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Service.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/Service.java
@@ -28,7 +28,7 @@ import javax.jms.MessageListener;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* Declare a queue and bind it to amq.direct with a 'well known' routing key,
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java
index be16f6b7ae..be16f6b7ae 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java
index 27371b0397..27371b0397 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/forwardall/SpecialQueue.java
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
index 7b3077a1c1..e67760a6c3 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
@@ -24,8 +24,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -333,9 +332,4 @@ public class ObjectMessageTest extends QpidTestCase implements MessageListener
{
return in + System.currentTimeMillis();
}
-
- public static junit.framework.Test suite()
- {
- return new VMBrokerSetup(new junit.framework.TestSuite(ObjectMessageTest.class));
- }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
index 4cdd7dd7e8..91cb37e455 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
@@ -20,14 +20,13 @@
*/
package org.apache.qpid.test.unit.client.protocol;
-import junit.framework.TestCase;
-
import org.apache.mina.common.IoSession;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.client.protocol.AMQProtocolSession;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.protocol.TestIoSession;
public class AMQProtocolSessionTest extends QpidTestCase
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
index 46b99fac8d..7a65b06dd4 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
@@ -30,9 +30,8 @@ import javax.jms.TemporaryQueue;
import javax.jms.TextMessage;
import junit.framework.Assert;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.transport.TransportConnection;
import java.util.List;
import java.util.LinkedList;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
index 54b2ee95f4..a61bcca049 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
@@ -22,9 +22,7 @@ package org.apache.qpid.test.unit.close;
import junit.framework.Assert;
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
index 5ebde71d6c..ec23256f38 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
@@ -21,11 +21,9 @@
package org.apache.qpid.test.unit.close;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.QpidClientConnection;
import org.apache.qpid.client.message.AbstractJMSMessage;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidClientConnection;
-import org.apache.qpid.testutil.QpidTestCase;
import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java
index 4957d700e6..da7642fb3c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java
@@ -24,12 +24,9 @@ import javax.jms.Topic;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* @author Apache Software Foundation
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
index 9caba63fe4..19b73fcc7c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/ct/DurableSubscriberTest.java
@@ -19,7 +19,7 @@ package org.apache.qpid.test.unit.ct;
import javax.jms.*;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* Crash Recovery tests for durable subscription
@@ -67,7 +67,7 @@ public class DurableSubscriberTest extends QpidTestCase
//now stop the server
try
{
- shutdownServer();
+ restartBroker();
}
catch (Exception e)
{
@@ -117,7 +117,7 @@ public class DurableSubscriberTest extends QpidTestCase
//now stop the server
try
{
- shutdownServer();
+ restartBroker();
}
catch (Exception e)
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
index 131cbd5f68..b30e3c1c1c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
@@ -25,7 +25,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
index 6883a09f1b..1f90f1e29f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java
@@ -20,15 +20,12 @@
*/
package org.apache.qpid.test.unit.message;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.NonQpidObjectMessage;
-import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,7 +76,7 @@ public class JMSPropertiesTest extends QpidTestCase
MessageProducer producer = producerSession.createProducer(queue);
Destination JMS_REPLY_TO = new AMQQueue(con2, "my.replyto");
// create a test message to send
- ObjectMessage sentMsg = new NonQpidObjectMessage();
+ ObjectMessage sentMsg = new NonQpidObjectMessage(producerSession);
sentMsg.setJMSCorrelationID(JMS_CORR_ID);
sentMsg.setJMSDeliveryMode(JMS_DELIV_MODE);
sentMsg.setJMSType(JMS_TYPE);
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
index d9d078a01d..6fa0172ae3 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
@@ -29,7 +29,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.BindingURL;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -106,7 +106,8 @@ public class StreamMessageTest extends QpidTestCase
_logger.info("Starting consumer connection");
con.start();
- StreamMessage msg2 = (StreamMessage) consumer.receive();
+ StreamMessage msg2 = (StreamMessage) consumer.receive(2000);
+ assertNotNull(msg2);
msg2.readByte();
try
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
index 6856ad34fb..2d3a98977f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
@@ -20,15 +20,10 @@
*/
package org.apache.qpid.test.unit.topic;
-import junit.framework.TestCase;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.url.URLSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -296,9 +291,9 @@ public class DurableSubscriptionTest extends QpidTestCase
"=TEST 'test", true);
assertNull("Subscriber should not have been created", deadSubscriber);
}
- catch (InvalidSelectorException e)
+ catch (JMSException e)
{
- // This was expected
+ assertTrue("Wrong type of exception thrown", e instanceof InvalidSelectorException);
}
TopicSubscriber liveSubscriber = session.createDurableSubscriber(topic, "testDurableWithInvalidSelectorSub");
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java
index 4f0f0dbaa9..6d115d1a2b 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicPublisherTest.java
@@ -28,7 +28,7 @@ import javax.jms.TopicSession;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* @author Apache Software Foundation
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
index 0ff3455624..7a20b1058b 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
@@ -30,13 +30,11 @@ import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
-import junit.framework.TestCase;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.client.AMQTopicSessionAdaptor;
+import org.apache.qpid.test.utils.QpidTestCase;
/** @author Apache Software Foundation */
@@ -141,13 +139,13 @@ public class TopicSessionTest extends QpidTestCase
public void testUnsubscriptionAfterConnectionClose() throws Exception
{
- AMQConnection con1 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con1 = (AMQConnection) getConnection("guest", "guest", "clientid");
AMQTopic topic = new AMQTopic(con1, "MyTopic3");
TopicSession session1 = con1.createTopicSession(false, AMQSession.AUTO_ACKNOWLEDGE);
TopicPublisher publisher = session1.createPublisher(topic);
- AMQConnection con2 = (AMQConnection) getConnection("guest", "guest");
+ AMQConnection con2 = (AMQConnection) getConnection("guest", "guest", "clientid");
TopicSession session2 = con2.createTopicSession(false, AMQSession.AUTO_ACKNOWLEDGE);
TopicSubscriber sub = session2.createDurableSubscriber(topic, "subscription0");
@@ -158,7 +156,7 @@ public class TopicSessionTest extends QpidTestCase
assertNotNull(tm);
con2.close();
publisher.publish(session1.createTextMessage("Hello2"));
- con2 = (AMQConnection) getConnection("guest", "guest");
+ con2 = (AMQConnection) getConnection("guest", "guest", "clientid");
session2 = con2.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
sub = session2.createDurableSubscriber(topic, "subscription0");
con2.start();
@@ -322,7 +320,7 @@ public class TopicSessionTest extends QpidTestCase
assertNull(m);
//send message to all consumers
- message = session1.createTextMessage("hello2");
+ message = session1.createTextMessage("hello2");
message.setStringProperty("Selector", "select");
publisher.publish(message);
@@ -365,6 +363,52 @@ public class TopicSessionTest extends QpidTestCase
con.close();
con2.close();
}
+
+ /**
+ * This tests QPID-1191, where messages which are sent to a topic but are not consumed by a subscriber
+ * due to a selector can be leaked.
+ * @throws Exception
+ */
+ public void testNonMatchingMessagesDoNotFillQueue() throws Exception
+ {
+ AMQConnection con = (AMQConnection) getConnection("guest", "guest");
+
+ // Setup Topic
+ AMQTopic topic = new AMQTopic(con, "testNoLocal");
+
+ TopicSession session = con.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+
+ // Setup subscriber with selector
+ TopicSubscriber selector = session.createSubscriber(topic, "Selector = 'select'", false);
+ TopicPublisher publisher = session.createPublisher(topic);
+
+ con.start();
+ TextMessage m;
+ TextMessage message;
+
+ // Send non-matching message
+ message = session.createTextMessage("non-matching 1");
+ publisher.publish(message);
+
+ // Send and consume matching message
+ message = session.createTextMessage("hello");
+ message.setStringProperty("Selector", "select");
+
+ publisher.publish(message);
+
+ m = (TextMessage) selector.receive(1000);
+ assertNotNull("should have received message", m);
+ assertEquals("Message contents were wrong", "hello", m.getText());
+
+ // Send non-matching message
+ message = session.createTextMessage("non-matching 2");
+ publisher.publish(message);
+
+ // Assert queue count is 0
+ long depth = ((AMQTopicSessionAdaptor) session).getSession().getQueueDepth(topic);
+ assertEquals("Queue depth was wrong", 0, depth);
+
+ }
public static junit.framework.Test suite()
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
index f2f35644c6..9c755fcb41 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
@@ -20,18 +20,14 @@
*/
package org.apache.qpid.test.unit.transacted;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.client.AMQConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-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.jms.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* This class tests a number of commits and roll back scenarios
@@ -503,4 +499,74 @@ public class CommitRollbackTest extends QpidTestCase
_session.commit();
}
+ /**
+ * Qpid-1163
+ * Check that when commt is called inside onMessage then
+ * the last message is nor redelivered.
+ *
+ * @throws Exception
+ */
+ public void testCommitWhithinOnMessage() throws Exception
+ {
+ Queue queue = (Queue) getInitialContext().lookup("queue");
+ // create a consumer
+ MessageConsumer cons = _session.createConsumer(queue);
+ MessageProducer prod = _session.createProducer(queue);
+ Message message = _session.createTextMessage("Message");
+ message.setJMSCorrelationID("m1");
+ prod.send(message);
+ _session.commit();
+ _logger.info("Sent message to queue");
+ CountDownLatch cd = new CountDownLatch(1);
+ cons.setMessageListener(new CommitWhithinOnMessageListener(cd));
+ conn.start();
+ cd.await(30, TimeUnit.SECONDS);
+ if( cd.getCount() > 0 )
+ {
+ fail("Did not received message");
+ }
+ // Check that the message has been dequeued
+ _session.close();
+ conn.close();
+ conn = (AMQConnection) getConnection("guest", "guest");
+ conn.start();
+ Session session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ cons = session.createConsumer(queue);
+ message = cons.receiveNoWait();
+ if(message != null)
+ {
+ if(message.getJMSCorrelationID().equals("m1"))
+ {
+ fail("received message twice");
+ }
+ else
+ {
+ fail("queue should have been empty, received message: " + message);
+ }
+ }
+ }
+
+ private class CommitWhithinOnMessageListener implements MessageListener
+ {
+ private CountDownLatch _cd;
+ private CommitWhithinOnMessageListener(CountDownLatch cd)
+ {
+ _cd = cd;
+ }
+ public void onMessage(Message message)
+ {
+ try
+ {
+ _logger.info("received message " + message);
+ assertEquals("Wrong message received", message.getJMSCorrelationID(), "m1");
+ _logger.info("commit session");
+ _session.commit();
+ _cd.countDown();
+ }
+ catch (JMSException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactedTest.java
index d96e8546e2..1eec6dd17c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactedTest.java
@@ -26,7 +26,7 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.jms.Session;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java
index 18cdb645c6..3906be2cc7 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/AbstractXATestCase.java
@@ -17,8 +17,8 @@
*/
package org.apache.qpid.test.unit.xa;
-import org.apache.qpidity.dtx.XidImpl;
-import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.dtx.XidImpl;
+import org.apache.qpid.test.utils.QpidTestCase;
import javax.transaction.xa.Xid;
import javax.transaction.xa.XAResource;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/xa/FaultTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
index 0adf39980b..0adf39980b 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/xa/FaultTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/FaultTest.java
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/xa/QueueTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java
index 740f9e72ad..d2abc0eac1 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/xa/QueueTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/QueueTest.java
@@ -372,7 +372,7 @@ public class QueueTest extends AbstractXATestCase
try
{
_logger.debug("stopping broker");
- shutdownServer();
+ restartBroker();
init();
}
catch (Exception e)
@@ -561,7 +561,7 @@ public class QueueTest extends AbstractXATestCase
try
{
_logger.debug("stopping broker");
- shutdownServer();
+ restartBroker();
init();
}
catch (Exception e)
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/xa/TopicTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java
index 027257d761..99d0f0a075 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/xa/TopicTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/xa/TopicTest.java
@@ -829,7 +829,7 @@ public class TopicTest extends AbstractXATestCase
/////// stop the broker now !!
try
{
- shutdownServer();
+ restartBroker();
init();
}
catch (Exception e)
@@ -1110,7 +1110,7 @@ public class TopicTest extends AbstractXATestCase
/////// stop the server now !!
try
{
- shutdownServer();
+ restartBroker();
init();
}
catch (Exception e)
@@ -1288,7 +1288,7 @@ public class TopicTest extends AbstractXATestCase
/////// stop the server now !!
try
{
- shutdownServer();
+ restartBroker();
init();
}
catch (Exception e)
diff --git a/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java b/java/systests/src/main/java/org/apache/qpid/test/utils/ConversationFactory.java
index 00cb458c86..bc68320224 100644
--- a/java/systests/src/main/java/org/apache/qpid/util/ConversationFactory.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/ConversationFactory.java
@@ -18,9 +18,10 @@
* under the License.
*
*/
-package org.apache.qpid.util;
+package org.apache.qpid.test.utils;
import org.apache.log4j.Logger;
+import org.apache.qpid.test.utils.ReflectionUtils;
import javax.jms.*;
diff --git a/java/systests/src/main/java/org/apache/qpid/test/FailoverBaseCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
index e939a06719..2fa6f4f417 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/FailoverBaseCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/FailoverBaseCase.java
@@ -18,25 +18,31 @@
* under the License.
*
*/
-package org.apache.qpid.test;
+package org.apache.qpid.test.utils;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.testutil.QpidTestCase;
import javax.jms.Connection;
public class FailoverBaseCase extends QpidTestCase
{
- protected long RECEIVE_TIMEOUT = 1000l;
+ private boolean failedOver = true;
+
protected void setUp() throws java.lang.Exception
{
super.setUp();
- if( _broker.equals(VM) )
+
+ try
+ {
+ TransportConnection.createVMBroker(2);
+ }
+ catch (Exception e)
{
- System.getProperties().setProperty("amqj.AutoCreateVMBroker", "true");
+ fail("Unable to create broker: " + e);
}
+
}
/**
@@ -60,13 +66,24 @@ public class FailoverBaseCase extends QpidTestCase
return conn;
}
+ public void tearDown() throws Exception
+ {
+ if (!failedOver)
+ {
+ TransportConnection.killVMBroker(2);
+ ApplicationRegistry.remove(2);
+ }
+ super.tearDown();
+ }
+
+
/**
* Only used of VM borker.
- * // TODO: update the failover mechanism once 0.10 provides support for failover.
*/
public void failBroker()
{
- TransportConnection.killVMBroker(1);
- ApplicationRegistry.remove(1);
+ failedOver = true;
+ TransportConnection.killVMBroker(2);
+ ApplicationRegistry.remove(2);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnection.java
index e99a51e1c7..35cab0fd33 100644
--- a/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnection.java
@@ -19,13 +19,11 @@
*
*/
-package org.apache.qpid.testutil;
+package org.apache.qpid.test.utils;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.client.JMSAMQException;
-import org.apache.qpid.url.URLSyntaxException;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java
index c43b65a805..72003ed7d7 100644
--- a/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java
@@ -19,7 +19,7 @@
*
*/
-package org.apache.qpid.testutil;
+package org.apache.qpid.test.utils;
import org.apache.log4j.Logger;
@@ -30,7 +30,6 @@ import org.apache.qpid.client.JMSAMQException;
import org.apache.qpid.url.URLSyntaxException;
import javax.jms.Connection;
-import javax.jms.DeliveryMode;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
diff --git a/java/client/src/main/java/org/apache/qpid/testutil/QpidTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java
index 1fe9a3ae51..65939e1fb7 100644
--- a/java/client/src/main/java/org/apache/qpid/testutil/QpidTestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java
@@ -15,24 +15,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.qpid.testutil;
+package org.apache.qpid.test.utils;
import junit.framework.TestCase;
import junit.framework.TestResult;
import javax.jms.Connection;
import javax.naming.InitialContext;
+import javax.naming.NamingException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionFactory;
-
+import org.apache.qpid.server.registry.ApplicationRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,8 +48,10 @@ public class QpidTestCase extends TestCase
private static final Logger _logger = LoggerFactory.getLogger(QpidTestCase.class);
+ protected long RECEIVE_TIMEOUT = 1000l;
+
/**
- * Some tests are excluded when the property test.excludes is set to true.
+ * Some tests are excluded when the property test.excludes is set to true.
* An exclusion list is either a file (prop test.excludesfile) which contains one test name
* to be excluded per line or a String (prop test.excludeslist) where tests to be excluded are
* separated by " ". Excluded tests are specified following the format:
@@ -55,6 +59,8 @@ public class QpidTestCase extends TestCase
* excluded and testName is the name of the test to be excluded.
* className#* excludes all the tests of the specified class.
*/
+ private static final String DEFAULT_INITIAL_CONTEXT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
static
{
if (Boolean.getBoolean("test.excludes"))
@@ -62,7 +68,7 @@ public class QpidTestCase extends TestCase
_logger.info("Some tests should be excluded, building the exclude list");
String exclusionListURI = System.getProperties().getProperty("test.excludesfile", "");
String exclusionListString = System.getProperties().getProperty("test.excludeslist", "");
- File file=new File(exclusionListURI);
+ File file = new File(exclusionListURI);
List<String> exclusionList = new ArrayList<String>();
if (file.exists())
{
@@ -83,7 +89,7 @@ public class QpidTestCase extends TestCase
_logger.warn("Exception when reading exclusion list", e);
}
}
- else if( ! exclusionListString.equals(""))
+ else if (!exclusionListString.equals(""))
{
_logger.info("Using excludeslist: " + exclusionListString);
// the exclusion list may be specified as a string
@@ -99,6 +105,13 @@ public class QpidTestCase extends TestCase
}
_exclusionList = exclusionList;
}
+
+ String initialContext = System.getProperty(InitialContext.INITIAL_CONTEXT_FACTORY);
+
+ if (initialContext == null || initialContext.length() == 0)
+ {
+ System.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT);
+ }
}
private static List<String> _exclusionList;
@@ -106,8 +119,9 @@ public class QpidTestCase extends TestCase
// system properties
private static final String BROKER = "broker";
private static final String BROKER_CLEAN = "broker.clean";
- private static final String BROKER_VERSION = "broker.version";
+ private static final String BROKER_VERSION = "broker.version";
private static final String BROKER_READY = "broker.ready";
+ private static final String TEST_OUTPUT = "test.output";
// values
protected static final String VM = "vm";
@@ -115,9 +129,12 @@ public class QpidTestCase extends TestCase
private static final String VERSION_08 = "0-8";
private static final String VERSION_010 = "0-10";
+ private static final String QPID_HOME = "QPID_HOME";
+
protected String _broker = System.getProperty(BROKER, VM);
private String _brokerClean = System.getProperty(BROKER_CLEAN, null);
private String _brokerVersion = System.getProperty(BROKER_VERSION, VERSION_08);
+ private String _output = System.getProperty(TEST_OUTPUT);
private Process _brokerProcess;
@@ -134,13 +151,28 @@ public class QpidTestCase extends TestCase
}
public QpidTestCase()
- {
- super("QpidTestCase");
- }
+ {
+ super("QpidTestCase");
+ }
public void runBare() throws Throwable
{
String name = getClass().getSimpleName() + "." + getName();
+ String qname = getClass().getName() + "." + getName();
+
+ PrintStream oldOut = System.out;
+ PrintStream oldErr = System.err;
+ PrintStream out = null;
+ PrintStream err = null;
+ boolean redirected = _output != null && _output.length() > 0;
+ if (redirected)
+ {
+ out = new PrintStream(String.format("%s/TEST-%s.out", _output, qname));
+ err = new PrintStream(String.format("%s/TEST-%s.err", _output, qname));
+ System.setOut(out);
+ System.setErr(err);
+ }
+
_logger.info("========== start " + name + " ==========");
startBroker();
try
@@ -158,13 +190,21 @@ public class QpidTestCase extends TestCase
_logger.error("exception stopping broker", e);
}
_logger.info("========== stop " + name + " ==========");
+
+ if (redirected)
+ {
+ System.setErr(oldErr);
+ System.setOut(oldOut);
+ err.close();
+ out.close();
+ }
}
}
public void run(TestResult testResult)
{
- if( _exclusionList != null && (_exclusionList.contains( getClass().getName() + "#*") ||
- _exclusionList.contains( getClass().getName() + "#" + getName())))
+ if (_exclusionList != null && (_exclusionList.contains(getClass().getName() + "#*") ||
+ _exclusionList.contains(getClass().getName() + "#" + getName())))
{
_logger.info("Test: " + getName() + " is excluded");
testResult.endTest(this);
@@ -175,7 +215,6 @@ public class QpidTestCase extends TestCase
}
}
-
private static final class Piper extends Thread
{
@@ -255,6 +294,15 @@ public class QpidTestCase extends TestCase
_logger.info("starting broker: " + _broker);
ProcessBuilder pb = new ProcessBuilder(_broker.split("\\s+"));
pb.redirectErrorStream(true);
+
+ Map<String, String> env = pb.environment();
+
+ String qpidHome = System.getProperty(QPID_HOME);
+ env.put(QPID_HOME, qpidHome);
+
+ //Augment Path with bin directory in QPID_HOME.
+ env.put("PATH", env.get("PATH").concat(File.pathSeparator + qpidHome + "/bin"));
+
_brokerProcess = pb.start();
Piper p = new Piper(_brokerProcess.getInputStream(),
@@ -325,13 +373,15 @@ public class QpidTestCase extends TestCase
else if (_broker.equals(VM))
{
TransportConnection.killAllVMBrokers();
+ ApplicationRegistry.removeAll();
}
_brokerStarted = false;
}
/**
* Check whether the broker is an 0.8
- * @return true if the broker is an 0_8 version, false otherwise.
+ *
+ * @return true if the broker is an 0_8 version, false otherwise.
*/
public boolean isBroker08()
{
@@ -343,20 +393,22 @@ public class QpidTestCase extends TestCase
return _brokerVersion.equals(VERSION_010);
}
- public void shutdownServer() throws Exception
+ public void restartBroker() throws Exception
{
stopBroker();
startBroker();
}
+
/**
* we assume that the environment is correctly set
* i.e. -Djava.naming.provider.url="..//example010.properties"
* TODO should be a way of setting that through maven
*
* @return an initial context
- * @throws Exception if there is an error getting the context
+ *
+ * @throws NamingException if there is an error getting the context
*/
- public InitialContext getInitialContext() throws Exception
+ public InitialContext getInitialContext() throws NamingException
{
_logger.info("get InitialContext");
if (_initialContext == null)
@@ -371,21 +423,22 @@ public class QpidTestCase extends TestCase
* Default factory is "local"
*
* @return A conection factory
+ *
* @throws Exception if there is an error getting the tactory
*/
- public AMQConnectionFactory getConnectionFactory() throws Exception
+ public AMQConnectionFactory getConnectionFactory() throws NamingException
{
_logger.info("get ConnectionFactory");
if (_connectionFactory == null)
{
- if (_broker.equals(VM))
- {
+ if (_broker.equals(VM))
+ {
_connectionFactory = getConnectionFactory("vm");
- }
- else
- {
+ }
+ else
+ {
_connectionFactory = getConnectionFactory("local");
- }
+ }
}
return _connectionFactory;
}
@@ -393,11 +446,13 @@ public class QpidTestCase extends TestCase
/**
* Get a connection factory for the currently used broker
*
- * @param factoryName The factory name
+ * @param factoryName The factory name
+ *
* @return A conection factory
+ *
* @throws Exception if there is an error getting the tactory
*/
- public AMQConnectionFactory getConnectionFactory(String factoryName) throws Exception
+ public AMQConnectionFactory getConnectionFactory(String factoryName) throws NamingException
{
return (AMQConnectionFactory) getInitialContext().lookup(factoryName);
}
@@ -412,13 +467,15 @@ public class QpidTestCase extends TestCase
*
* @param username The user name
* @param password The user password
+ *
* @return a newly created connection
+ *
* @throws Exception if there is an error getting the connection
*/
public Connection getConnection(String username, String password) throws Exception
{
_logger.info("get Connection");
- Connection con = getConnectionFactory().createConnection(username, password);
+ Connection con = getConnectionFactory().createConnection(username, password);
//add the connection in the lis of connections
_connections.add(con);
return con;
@@ -434,9 +491,9 @@ public class QpidTestCase extends TestCase
}
else
{
- con = getConnectionFactory().createConnection(username, password);
+ con = getConnectionFactory().createConnection(username, password, id);
}
- //add the connection in the lis of connections
+ //add the connection in the lis of connections
_connections.add(con);
return con;
}
diff --git a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtils.java
index 28fb2e0c8a..7946c6a6d1 100644
--- a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtils.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.util;
+package org.apache.qpid.test.utils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
diff --git a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java b/java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtilsException.java
index c2862a755b..838828598b 100644
--- a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/ReflectionUtilsException.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.util;
+package org.apache.qpid.test.utils;
/**
* Wraps a checked exception that occurs when {@link ReflectionUtils} encounters checked exceptions using standard
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/TestIoSession.java b/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java
index d14e0b771f..f1eb8159b6 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/protocol/TestIoSession.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/protocol/TestIoSession.java
@@ -18,7 +18,7 @@
* under the License.
*
*/
-package org.apache.qpid.test.unit.client.protocol;
+package org.apache.qpid.test.utils.protocol;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
diff --git a/java/testkit/README b/java/testkit/README
new file mode 100644
index 0000000000..fdde734027
--- /dev/null
+++ b/java/testkit/README
@@ -0,0 +1,153 @@
+Introduction
+============
+
+The Test kit for the java client consists of 2 components.
+
+1) A Simple Perf Test that can be used to,
+ a) Run a predefined perf report consisting of 8 use cases (see below)
+ b) Run a producer and a consumer with a number of different options
+
+2) Soak tests that can be run for longer durations (hours or days).
+
+I am planning to add some stress tests to this module as well.
+Please note this is not a replacement for the existing perf/systests etc.
+But rather a small test kit thats focused on providing a packaged set of tests that can be quickly deployed on an environment to do quick smoke testing or easily setup a soak test.
+
+Table of Contents
+=================
+1. Perf Kit
+2. Soak Kit
+3. Perf Test use cases
+4. Soak Test use cases
+5. Running the sample perf test report
+6. Running the sample soak test report
+
+1.0 Perf Kit
+------------
+1.1 The perf kit can be packaged as an RPM or a tar file and deploy on a target environment and run the perf report.
+Or else a perf report can be automated to run every day or so an record numbers to catch perf regressions.
+
+1.2 It calculates the following results in msg/sec.
+
+ System throuhgput : no_of_msgs / (time_last_msg_rcvd - time_first_msg_send)
+
+ Producer rate : no_of_msgs / (time_after_sending - time_before_sending)
+
+ Producer rate : no_of_msgs / (time_last_msg_rcvd - time_first_msg_rcvd)
+
+ Latency : time_msg_rcvd - time_msg_sent
+
+The test will print min, max and avg latency.
+
+1.3 The test assume that both producer and consumer are run on the same machine or different machines that are time synced.
+
+1.4 You can also use run_sub.sh and run_pub.sh to run different use cases with several options.
+ Please look at TestParams.java for all the configurable options.
+
+1.5 You can also use the test kit to benchmark against any vendor.
+
+
+2.0 Soak tests
+--------------
+2.0 This includes a set of soak tests that can be run for a longer duration.
+
+2.1 A typical test will send x-1 messages and the xth message will contain an "End" marker.
+ The producer will print the timestamp as soon as it sends the xth message.
+ The consumer will reply with an empty message to the replyTo destination given in the xth message.
+ The consumer prints the throuhgput for the iteration and the latency for the xth message.
+ A typical value for x is 100k
+
+2.2 The feedback loop prevents the producer from overrunning the consumer.
+ And the printout for every xth message will let you know how many iterations been completed at any given time.
+ (Ex a simple cat log | wc -l will give you the how many iterations have been completed so far).
+
+2.2 The following results can be calculated for these tests.
+
+ Memory, CPU for each producer/consumer - look at testkit/bin/run_soak_client.sh for an example
+
+ You can find the Avg, Min & Max for throughput, latency, CPU and memory for the entire test run.
+ (look at testkit/bin/soak_report.sh) for an example).
+
+ You could also graph throughput, latency, CPU and memory using the comma separated log files.
+
+2.2 If you use different machines for producer and consumer the machines have to be time synced to have meaningful latency samples.
+
+3.0 Perf Test report use cases
+-------------------------------
+3.1 Please check testkit/bin/perf_report.sh for more details
+
+3.2 A typical test run will send 1000 msgs during warmup and 200k msgs for result calculation.
+
+Test 1 Trans Queue
+
+Test 2 Dura Queue
+
+Test 3 Dura Queue Sync
+
+Test 4 Topic
+
+Test 5 Durable Topic
+
+Test 6 Fanout
+
+Test 7 Small TX (about 2 msgs per tx)
+
+Test 8 Large TX (about 1000 msgs per tx)
+
+
+4.0 Soak tests use cases
+-------------------------
+4.1 Following are the current tests available in the test kit.
+
+4.2 Please refer to the source to see the javadoc and options
+
+
+1. SimpleProducer/Consumer sends X messages at a time and will wait for confirmation from producer before proceeding with the next iteration. A no of options can be configured.
+
+2. MultiThreadedProducer/Consumer does the same thing as above but runs each session in a separate thread.
+ It can also send messages transactionally. Again a no of options can be configured.
+
+3. ResourceLeakTest will setup consumer/producers sends x messages and then teard down everything and continue again.
+
+
+5.0 Running the sample perf test report
+---------------------------------------
+The testkit/bin contains perf_report.sh.
+It runs the above 8 use cases against a broker and print the results in a tabular format.
+
+For example
+================================================================================================
+|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|
+------------------------------------------------------------------------------------------------
+|Trans_Queue | xxxxx.xx| xxxxx.xx| xxxxx.xx| xx.xx| x| xx|
+
+
+5.1 running perf_report.sh
+
+5.1.1 set JAVA_HOME to point to Java 1.5 and above
+5.1.2 set QPID_TEST_HOME to point to the testkit dir
+5.1.3 set VENDOR_LIB to point to the Qpid (or other JMS providers) jar files.
+5.1.4 start a broker
+5.1.5 update the testkit/etc/jndi.properties to point to the correct broker
+5.1.6 execute perf_report.sh
+
+
+6.0 Running the sample soak test report
+---------------------------------------
+The testkit/bin contains soak_report.sh
+It runs MultiThreadedProducer/Consumer for the duration specified and prints a report for the following stats.
+Avg, Min and Max for System Throughput, letency, CPU and memory.
+
+6.1 running soak_report.sh
+
+5.1.1 set JAVA_HOME to point to Java 1.5 and above
+5.1.2 set QPID_TEST_HOME to point to the testkit dir
+5.1.3 set JAR_PATH to point to the Qpid jars
+5.1.4 start a broker
+5.1.5 execute soak_report.sh with correct params.
+ Ex sh soak_report.sh 1 36000 will run for 10 hours colllecting CPU, memory every second.
+
+5.1.6 Please note the total duration for the test is log_freq * log_iterations
+ So if you want to run the test for 10 hours and collect 10 second samples then do the following
+ sh soak_report.sh 10 3600
+
diff --git a/java/testkit/bin/perf_report.sh b/java/testkit/bin/perf_report.sh
new file mode 100644
index 0000000000..9e574cad7a
--- /dev/null
+++ b/java/testkit/bin/perf_report.sh
@@ -0,0 +1,100 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# This will run the 8 use cases defined below and produce
+# a report in tabular format. Refer to the documentation
+# for more details.
+
+SUB_MEM=-Xmx1024M
+PUB_MEM=-Xmx1024M
+LOG_CONFIG=-Dlog4j.configuration="$QPID_TEST_HOME/etc/test.log4j"
+
+. setenv.sh
+
+waitfor() { until grep -a -l "$2" $1 >/dev/null 2>&1 ; do sleep 1 ; done ; }
+cleanup()
+{
+ pids=`ps aux | grep java | grep Perf | awk '{print $2}'`
+ if [ "$pids" != "" ]; then
+ kill -3 $pids
+ kill -9 $pids >/dev/null 2>&1
+ fi
+}
+
+# $1 test name
+# $2 consumer options
+# $3 producer options
+run_testcase()
+{
+ sh run_sub.sh $LOG_CONFIG $SUB_MEM $2 > sub.out &
+ waitfor sub.out "Warming up"
+ sh run_pub.sh $LOG_CONFIG $PUB_MEM $3 > pub.out &
+ waitfor sub.out "Completed the test"
+ waitfor pub.out "Consumer has completed the test"
+ sleep 2 #give a grace period to shutdown
+ print_result $1
+}
+
+print_result()
+{
+ prod_rate=`cat pub.out | grep "Producer rate" | awk '{print $3}'`
+ sys_rate=`cat sub.out | grep "System Throughput" | awk '{print $4}'`
+ cons_rate=`cat sub.out | grep "Consumer rate" | awk '{print $4}'`
+ avg_latency=`cat sub.out | grep "Avg Latency" | awk '{print $4}'`
+ min_latency=`cat sub.out | grep "Min Latency" | awk '{print $4}'`
+ max_latency=`cat sub.out | grep "Max Latency" | awk '{print $4}'`
+
+ printf "|%-15s|%15.2f|%13.2f|%13.2f|%11.2f|%11d|%11d|\n" $1 $sys_rate $prod_rate $cons_rate $avg_latency $min_latency $max_latency
+ echo "------------------------------------------------------------------------------------------------"
+}
+
+trap cleanup EXIT
+
+echo "Test report on " `date +%F`
+echo "================================================================================================"
+echo "|Test |System throuput|Producer rate|Consumer Rate|Avg Latency|Min Latency|Max Latency|"
+echo "------------------------------------------------------------------------------------------------"
+
+# Test 1 Trans Queue
+run_testcase "Trans_Queue" "" "-Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 2 Dura Queue
+run_testcase "Dura_Queue" "-Ddurable=true" "-Ddurable=true -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 3 Dura Queue Sync
+run_testcase "Dura_Queue_Sync" "-Ddurable=true" "-Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dsync_persistence=true"
+
+# Test 4 Topic
+run_testcase "Topic" "-DtransDest=transientTopic" "-DtransDest=transientTopic -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 5 Durable Topic
+#run_testcase "Dura_Topic" "-Ddurable=true -DtransDest=durableTopic" "-Ddurable=true -DtransDest=durableTopic -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 6 Fanout
+run_testcase "Fanout" "-DtransDest=fanoutQueue" "-DtransDest=fanoutQueue -Dwarmup_count=1 -Dmsg_count=10"
+
+# Test 7 Small TX
+run_testcase "Small_Txs_2" "-Ddurable=true -Dtransacted=true -Dtrans_size=1" \
+ "-Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=1"
+
+# Test 8 Large TX
+run_testcase "Large_Txs_1000" "-Ddurable=true -Dtransacted=true -Dtrans_size=10" \
+ "-Ddurable=true -Dwarmup_count=1 -Dmsg_count=10 -Dtransacted=true -Dtrans_size=10"
+
diff --git a/java/testkit/bin/run_pub.sh b/java/testkit/bin/run_pub.sh
new file mode 100644
index 0000000000..0702a55de9
--- /dev/null
+++ b/java/testkit/bin/run_pub.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+. $QPID_TEST_HOME/bin/setenv.sh
+
+echo "$@"
+$JAVA_HOME/bin/java -cp $CLASSPATH $@ org.apache.qpid.testkit.perf.PerfProducer
diff --git a/java/testkit/bin/run_soak_client.sh b/java/testkit/bin/run_soak_client.sh
new file mode 100644
index 0000000000..ea1721d988
--- /dev/null
+++ b/java/testkit/bin/run_soak_client.sh
@@ -0,0 +1,70 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# This is a sample script for a soak test on
+# linux environment.
+# This will start n of Producers processors and record their CPU and memory stats.
+# Also the Producer out will be saved to a file as well.
+
+if [ "$JAR_PATH" = "" ] ; then
+ echo "ERROR: Please set JAR_PATH to point to the Qpid libraries ...."
+ exit 1
+fi
+
+#1 PID, $2 freq, $3 count
+calc_stats(){
+
+for (( i = 0 ; i <= $3; i++ ))
+ do
+ cpu=`ps auxw | grep $1 | grep -v 'grep' | awk '{print $3}'`
+ mem=`pmap $1 | grep total | grep -v 'grep' | awk '{print substr($2,0,length($2)-1)}'`
+ echo $i","$mem","$cpu
+ sleep $2
+ cpu="0.0"
+ mem="0"
+ done
+ kill -9 $1
+}
+
+# Num of producer processors to start
+num=$1
+# Log frequency in seconds
+log_freq=$2
+# Num of iterations
+log_iter=$3
+
+class_name=$4
+log_file_name=`echo $class_name | cut -d. -f6`
+
+# The total time for the test is determined by the
+# log_freq * log_iter.
+
+shift 4
+CLASSPATH=`find $JAR_PATH -name '*.jar' | tr '\n' ":"`
+
+JVM_ARGS="-Xmx1500M $@"
+echo "Starting $log_file_name with the following params $JVM_ARGS"
+
+for (( c = 1 ; c <= $num; c++ ))
+do
+ $JAVA_HOME/bin/java $JVM_ARGS -cp $CLASSPATH $class_name > ${log_file_name}_${c}.log &
+ pid=`jobs -l %% | awk '{print $2}'`
+ calc_stats $pid $log_freq $log_iter > ${log_file_name}_process_${c}.log &
+done
diff --git a/java/testkit/bin/run_sub.sh b/java/testkit/bin/run_sub.sh
new file mode 100644
index 0000000000..f7e687de38
--- /dev/null
+++ b/java/testkit/bin/run_sub.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+. $QPID_TEST_HOME/bin/setenv.sh
+
+echo "$@"
+$JAVA_HOME/bin/java -cp $CLASSPATH $@ org.apache.qpid.testkit.perf.PerfConsumer
+
diff --git a/java/testkit/bin/setenv.sh b/java/testkit/bin/setenv.sh
new file mode 100644
index 0000000000..24135e711b
--- /dev/null
+++ b/java/testkit/bin/setenv.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Compiles the test classes and sets the CLASSPATH
+
+# check for QPID_TEST_HOME
+if [ "$QPID_TEST_HOME" = "" ] ; then
+ echo "ERROR: Please set QPID_TEST_HOME ...."
+ exit 1
+fi
+
+# check for JAVA_HOME
+if [ "$JAVA_HOME" = "" ] ; then
+ echo "ERROR: Please set JAVA_HOME ...."
+ exit 1
+fi
+
+# VENDOR_LIB path needs to be set
+# for Qpid set this to {qpid_checkout}/java/build/lib
+if [ "$VENDOR_LIB" = "" ] ; then
+ echo "ERROR: Please set VENDOR_LIB path in the script ...."
+ exit 1
+fi
+
+
+[ -d $QPID_TEST_HOME/classes ] || mkdir $QPID_TEST_HOME/classes
+
+CLASSPATH=`find $VENDOR_LIB -name *.jar* | tr '\n' ":"`
+$JAVA_HOME/bin/javac -cp $CLASSPATH -d $QPID_TEST_HOME/classes -sourcepath $QPID_TEST_HOME/src `find $QPID_TEST_HOME/src -name '*.java'`
+
+export CLASSPATH=$QPID_TEST_HOME/classes:$CLASSPATH
+
diff --git a/java/testkit/bin/soak_report.sh b/java/testkit/bin/soak_report.sh
new file mode 100644
index 0000000000..9da8bfa234
--- /dev/null
+++ b/java/testkit/bin/soak_report.sh
@@ -0,0 +1,161 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Sample script to run a soak test with MultiThreadedProducer/Consumer.
+# You need to provide the log freq and no of iterations
+# Ex to run 10 hours and collect 1 second samples
+# soak_report.sh 1 36000
+
+# This script assumes that a suitable broker instance is started.
+
+log_freq=$1
+log_iter=$2
+shift 2
+JVM_ARGS=$@
+
+if [ "$QPID_TEST_HOME" = "" ] ; then
+ echo "ERROR: Please set QPID_TEST_HOME ...."
+ exit 1
+fi
+
+print_rates()
+{
+ cat $1 | awk '{
+ FS = ",";
+ count = 0;
+ total_latency = 0;
+ min_latency = 9223372036854775807;
+ max_latency = 0;
+
+ total_tp = 0;
+ min_tp = 50000;
+ max_tp = 0;
+
+ while ((getline) == 1)
+ {
+ total_latency = total_latency + $3
+ total_tp = total_tp + $2
+
+ if ($3 > 0)
+ {
+ min_latency = (($3 < min_latency) ? $3 : min_latency);
+ max_latency = (($3 > max_latency) ? $3 : max_latency);
+ }
+ if ($2 > 0)
+ {
+ min_tp = (($2 < min_tp) ? $2 : min_tp);
+ max_tp = (($2 > max_tp) ? $2 : max_tp);
+ }
+
+ count = count + 1
+ }
+
+ print "Avg Latency (ms) : " total_latency/count
+ print "Max Latency (ms) : " max_latency
+ print "Min Latency (ms) : " min_latency
+
+ print ""
+ print "Avg Throughput (msg/sec) : " total_tp/count
+ print "Max Throughput (msg/sec) : " max_tp
+ print "Min Throughput (msg/sec) : " min_tp
+
+ print ""
+ print "Total Iteratons " count
+
+ }'
+}
+
+print_system_stats()
+{
+ cat $1 | awk '{
+ FS = ",";
+ count = 0;
+ total_memory = 0;
+ min_memory = 9223372036854775807;
+ max_memory = 0;
+
+ total_cp = 0;
+ min_cp = 50000;
+ max_cp = 0;
+
+ while ((getline) == 1)
+ {
+ total_memory = total_memory + $2
+ total_cp = total_cp + $3
+
+ if ($2 > 0)
+ {
+ min_memory = (($2 < min_memory) ? $2 : min_memory);
+ max_memory = (($2 > max_memory) ? $2 : max_memory);
+ }
+ if ($3 > 0)
+ {
+ min_cp = (($3 < min_cp) ? $3 : min_cp);
+ max_cp = (($3 > max_cp) ? $3 : max_cp);
+ }
+
+ count = count + 1
+ }
+
+ print "Avg Memory (MB) : " total_memory/(count*1024)
+ print "Max Memory (MB) : " max_memory/1024
+ print "Min Memory (MB) : " min_memory/1024
+
+ print ""
+ print "Avg CPU : " total_cp/count
+ print "Max CPU : " max_cp
+ print "Min CPU : " min_cp
+
+ print ""
+ print "Total Iteratons " count
+
+ }'
+}
+
+
+cleanup()
+{
+ kill -9 `ps aux | grep java | grep soak | awk '{ print $2 }'`
+}
+
+print_results()
+{
+ printf "\n======================================================= \n"
+ print_rates MultiThreadedConsumer_1.log
+ printf "\nConsumer process stats "
+ printf "\n----------------------- \n"
+ print_system_stats MultiThreadedConsumer_process_1.log
+ printf "\nProducer process stats "
+ printf "\n----------------------- \n"
+ print_system_stats MultiThreadedProducer_process_1.log
+ printf "\n------------------------------------------------------- \n"
+}
+
+trap cleanup EXIT
+
+# runs a single instance of the MultiThreadedConsumer and MultiThreadedProducer
+sh $QPID_TEST_HOME/bin/run_soak_client.sh 1 $log_freq $log_iter org.apache.qpid.testkit.soak.MultiThreadedConsumer $JVM_ARGS
+sh $QPID_TEST_HOME/bin/run_soak_client.sh 1 $log_freq $log_iter org.apache.qpid.testkit.soak.MultiThreadedProducer $JVM_ARGS
+
+sleep_time=$((log_freq * log_iter))
+echo "sleep time : " $sleep_time
+sleep $((log_freq * log_iter))
+
+print_results
diff --git a/java/testkit/build.xml b/java/testkit/build.xml
new file mode 100644
index 0000000000..94b97d270d
--- /dev/null
+++ b/java/testkit/build.xml
@@ -0,0 +1,27 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<project name="Test Kit" default="build">
+
+ <property name="module.depends" value="client broker common"/>
+
+ <import file="../module.xml"/>
+
+</project>
diff --git a/java/testkit/etc/jndi.properties b/java/testkit/etc/jndi.properties
new file mode 100644
index 0000000000..f535975844
--- /dev/null
+++ b/java/testkit/etc/jndi.properties
@@ -0,0 +1,35 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
+
+# use the following property to configure the default connector
+#java.naming.provider.url - ignored.
+
+# register some connection factories
+# connectionfactory.[jndiname] = [ConnectionURL]
+connectionfactory.connectionFactory = amqp://guest:guest@clientid/testpath?brokerlist='tcp://localhost:5672'
+
+# Register an AMQP destination in JNDI
+destination.transientQueue = direct://amq.direct//testQueueT
+destination.durableQueue = direct://amq.direct//testQueueD?durable='true'
+
+destination.transientTopic = topic://amq.topic//testTopicT
+#destination.durableTopic = topic://amq.topic//testTopicD?durable='true'
+
+destination.fanoutQueue = fanout://amq.fanout//fanoutQueue \ No newline at end of file
diff --git a/java/testkit/etc/test.log4j b/java/testkit/etc/test.log4j
new file mode 100644
index 0000000000..b574a7b5b7
--- /dev/null
+++ b/java/testkit/etc/test.log4j
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+log4j.rootLogger=${root.logging.level}
+
+log4j.logger.org.apache.qpid=ERROR, console
+log4j.additivity.org.apache.qpid=false
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.Threshold=all
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
+
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/MessageFactory.java b/java/testkit/src/main/java/org/apache/qpid/testkit/MessageFactory.java
new file mode 100644
index 0000000000..f2784ef499
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/MessageFactory.java
@@ -0,0 +1,43 @@
+package org.apache.qpid.testkit;
+
+import javax.jms.BytesMessage;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+public class MessageFactory
+{
+ public static Message createBytesMessage(Session ssn, int size) throws JMSException
+ {
+ BytesMessage msg = ssn.createBytesMessage();
+ msg.writeBytes(createMessagePayload(size).getBytes());
+ return msg;
+ }
+
+ public static Message createTextMessage(Session ssn, int size) throws JMSException
+ {
+ TextMessage msg = ssn.createTextMessage();
+ msg.setText(createMessagePayload(size));
+ return msg;
+ }
+
+ public static String createMessagePayload(int size)
+ {
+ String msgData = "Qpid Test Message";
+
+ StringBuffer buf = new StringBuffer(size);
+ int count = 0;
+ while (count <= (size - msgData.length()))
+ {
+ buf.append(msgData);
+ count += msgData.length();
+ }
+ if (count < size)
+ {
+ buf.append(msgData, 0, size - count);
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfBase.java b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfBase.java
new file mode 100644
index 0000000000..95670f0507
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfBase.java
@@ -0,0 +1,102 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.perf;
+
+import java.text.DecimalFormat;
+import java.util.Hashtable;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.Session;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+public class PerfBase
+{
+ TestParams params;
+ Connection con;
+ Session session;
+ Destination dest;
+ Destination feedbackDest;
+ DecimalFormat df = new DecimalFormat("###.##");
+
+ public PerfBase()
+ {
+ params = new TestParams();
+ }
+
+ public void setUp() throws Exception
+ {
+ Hashtable<String,String> env = new Hashtable<String,String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, params.getInitialContextFactory());
+ env.put(Context.PROVIDER_URL, params.getProviderURL());
+
+ Context ctx = null;
+ try
+ {
+ ctx = new InitialContext(env);
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Error initializing JNDI",e);
+
+ }
+
+ ConnectionFactory conFac = null;
+ try
+ {
+ conFac = (ConnectionFactory)ctx.lookup(params.getConnectionFactory());
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Error looking up connection factory",e);
+ }
+
+ con = conFac.createConnection();
+ con.start();
+ session = con.createSession(params.isTransacted(),
+ params.isTransacted()? Session.SESSION_TRANSACTED:params.getAckMode());
+
+ try
+ {
+ dest = (Destination)ctx.lookup( params.isDurable()?
+ params.getDurableDestination():
+ params.getTransientDestination()
+ );
+ }
+ catch(Exception e)
+ {
+ throw new Exception("Error looking up destination",e);
+ }
+ }
+
+ public void handleError(Exception e,String msg)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(msg);
+ sb.append(" ");
+ sb.append(e.getMessage());
+ System.err.println(sb.toString());
+ e.printStackTrace();
+ }
+}
+
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfConsumer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfConsumer.java
new file mode 100644
index 0000000000..cd12c7010d
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfConsumer.java
@@ -0,0 +1,248 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.perf;
+
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.TextMessage;
+
+/**
+ * PerfConsumer will receive x no of messages in warmup mode.
+ * Once it receives the Start message it will then signal the PerfProducer.
+ * It will start recording stats from the first message it receives after
+ * the warmup mode is done.
+ *
+ * The following calculations are done.
+ * The important numbers to look at is
+ * a) Avg Latency
+ * b) System throughput.
+ *
+ * Latency.
+ * =========
+ * Currently this test is written with the assumption that either
+ * a) The Perf Producer and Consumer are on the same machine
+ * b) They are on separate machines that have their time synced via a Time Server
+ *
+ * In order to calculate latency the producer inserts a timestamp
+ * hen the message is sent. The consumer will note the current time the message is
+ * received and will calculate the latency as follows
+ * latency = rcvdTime - msg.getJMSTimestamp()
+ *
+ * Through out the test it will keep track of the max and min latency to show the
+ * variance in latencies.
+ *
+ * Avg latency is measured by adding all latencies and dividing by the total msgs.
+ * You can also compute this by (rcvdTime - testStartTime)/rcvdMsgCount
+ *
+ * Throughput
+ * ===========
+ * System throughput is calculated as follows
+ * rcvdMsgCount/(rcvdTime - testStartTime)
+ *
+ * Consumer rate is calculated as
+ * rcvdMsgCount/(rcvdTime - startTime)
+ *
+ * Note that the testStartTime referes to when the producer sent the first message
+ * and startTime is when the consumer first received a message.
+ *
+ * rcvdTime keeps track of when the last message is received.
+ *
+ * All throughput rates are given as msg/sec so the rates are multiplied by 1000.
+ *
+ */
+
+public class PerfConsumer extends PerfBase implements MessageListener
+{
+ MessageConsumer consumer;
+ long maxLatency = 0;
+ long minLatency = Long.MAX_VALUE;
+ long totalLatency = 0; // to calculate avg latency.
+ int rcvdMsgCount = 0;
+ long testStartTime = 0; // to measure system throughput
+ long startTime = 0; // to measure consumer throughput
+ long rcvdTime = 0;
+ boolean transacted = false;
+ int transSize = 0;
+
+ final Object lock = new Object();
+
+ public PerfConsumer()
+ {
+ super();
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ consumer = session.createConsumer(dest);
+
+ // Storing the following two for efficiency
+ transacted = params.isTransacted();
+ transSize = params.getTransactionSize();
+ }
+
+ public void warmup()throws Exception
+ {
+ System.out.println("Warming up......");
+
+ boolean start = false;
+ while (!start)
+ {
+ Message msg = consumer.receive();
+ if (msg instanceof TextMessage)
+ {
+ if (((TextMessage)msg).getText().equals("End"))
+ {
+ start = true;
+ MessageProducer temp = session.createProducer(msg.getJMSReplyTo());
+ temp.send(session.createMessage());
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+ temp.close();
+ }
+ }
+ }
+ }
+
+ public void startTest() throws Exception
+ {
+ System.out.println("Starting test......");
+ consumer.setMessageListener(this);
+ }
+
+ public void printResults() throws Exception
+ {
+ synchronized (lock)
+ {
+ lock.wait();
+ }
+
+ double avgLatency = (double)totalLatency/(double)rcvdMsgCount;
+ double throughput = ((double)rcvdMsgCount/(double)(rcvdTime - testStartTime))*1000;
+ double consRate = ((double)rcvdMsgCount/(double)(rcvdTime - startTime))*1000;
+ System.out.println(new StringBuilder("Total Msgs Received : ").append(rcvdMsgCount).toString());
+ System.out.println(new StringBuilder("Consumer rate : ").
+ append(df.format(consRate)).
+ append(" msg/sec").toString());
+ System.out.println(new StringBuilder("System Throughput : ").
+ append(df.format(throughput)).
+ append(" msg/sec").toString());
+ System.out.println(new StringBuilder("Avg Latency : ").
+ append(df.format(avgLatency)).
+ append(" ms").toString());
+ System.out.println(new StringBuilder("Min Latency : ").
+ append(minLatency).
+ append(" ms").toString());
+ System.out.println(new StringBuilder("Max Latency : ").
+ append(maxLatency).
+ append(" ms").toString());
+ System.out.println("Completed the test......\n");
+ }
+
+ public void notifyCompletion(Destination replyTo) throws Exception
+ {
+ MessageProducer tmp = session.createProducer(replyTo);
+ Message endMsg = session.createMessage();
+ tmp.send(endMsg);
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+ tmp.close();
+ }
+
+ public void tearDown() throws Exception
+ {
+ consumer.close();
+ session.close();
+ con.close();
+ }
+
+ public void onMessage(Message msg)
+ {
+ try
+ {
+ if (msg instanceof TextMessage && ((TextMessage)msg).getText().equals("End"))
+ {
+ notifyCompletion(msg.getJMSReplyTo());
+
+ synchronized (lock)
+ {
+ lock.notifyAll();
+ }
+ }
+ else
+ {
+ rcvdTime = System.currentTimeMillis();
+ rcvdMsgCount ++;
+
+ if (rcvdMsgCount == 1)
+ {
+ startTime = rcvdTime;
+ testStartTime = msg.getJMSTimestamp();
+ }
+
+ if (transacted && (rcvdMsgCount % transSize == 0))
+ {
+ session.commit();
+ }
+
+ long latency = rcvdTime - msg.getJMSTimestamp();
+ maxLatency = Math.max(maxLatency, latency);
+ minLatency = Math.min(minLatency, latency);
+ totalLatency = totalLatency + latency;
+ }
+
+ }
+ catch(Exception e)
+ {
+ handleError(e,"Error when receiving messages");
+ }
+
+ }
+
+ public void test()
+ {
+ try
+ {
+ setUp();
+ warmup();
+ startTest();
+ printResults();
+ tearDown();
+ }
+ catch(Exception e)
+ {
+ handleError(e,"Error when running test");
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ PerfConsumer cons = new PerfConsumer();
+ cons.test();
+ }
+} \ No newline at end of file
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfProducer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfProducer.java
new file mode 100644
index 0000000000..757b1bfcda
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/PerfProducer.java
@@ -0,0 +1,207 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.perf;
+
+import javax.jms.BytesMessage;
+import javax.jms.DeliveryMode;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+
+import org.apache.qpid.testkit.MessageFactory;
+
+/**
+ * PerfProducer sends an x no of messages in warmup mode and wait for a confirmation
+ * from the consumer that it has successfully consumed them and ready to start the
+ * test. It will start sending y no of messages and each message will contain a time
+ * stamp. This will be used at the receiving end to measure the latency.
+ *
+ * This is done with the assumption that both consumer and producer are running on
+ * the same machine or different machines which have time synced using a time server.
+ *
+ * This test also calculates the producer rate as follows.
+ * rate = msg_count/(time_before_sending_msgs - time_after_sending_msgs)
+ *
+ * All throughput rates are given as msg/sec so the rates are multiplied by 1000.
+ *
+ * Rajith - Producer rate is not an accurate perf metric IMO.
+ * It is heavily inlfuenced by any in memory buffering.
+ * System throughput and latencies calculated by the PerfConsumer are more realistic
+ * numbers.
+ *
+ */
+public class PerfProducer extends PerfBase
+{
+ MessageProducer producer;
+ Message msg;
+ byte[] payload;
+
+ public PerfProducer()
+ {
+ super();
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ feedbackDest = session.createTemporaryQueue();
+
+ // if message caching is enabled we pre create the message
+ // else we pre create the payload
+ if (params.isCacheMessage())
+ {
+ msg = MessageFactory.createBytesMessage(session, params.getMsgSize());
+ msg.setJMSDeliveryMode(params.isDurable()?
+ DeliveryMode.PERSISTENT :
+ DeliveryMode.NON_PERSISTENT
+ );
+ }
+ else
+ {
+ payload = MessageFactory.createMessagePayload(params.getMsgSize()).getBytes();
+ }
+
+ producer = session.createProducer(dest);
+ producer.setDisableMessageID(params.isDisableMessageID());
+ producer.setDisableMessageTimestamp(params.isDisableTimestamp());
+ }
+
+ protected Message getNextMessage() throws Exception
+ {
+ if (params.isCacheMessage())
+ {
+ return msg;
+ }
+ else
+ {
+ msg = session.createBytesMessage();
+ ((BytesMessage)msg).writeBytes(payload);
+ return msg;
+ }
+ }
+
+ public void warmup()throws Exception
+ {
+ System.out.println("Warming up......");
+ MessageConsumer tmp = session.createConsumer(feedbackDest);
+
+ for (int i=0; i < params.getWarmupCount() -1; i++)
+ {
+ producer.send(getNextMessage());
+ }
+ Message msg = session.createTextMessage("End");
+ msg.setJMSReplyTo(feedbackDest);
+ producer.send(msg);
+
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.receive();
+
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.close();
+ }
+
+ public void startTest() throws Exception
+ {
+ System.out.println("Starting test......");
+ int count = params.getMsgCount();
+ boolean transacted = params.isTransacted();
+ int tranSize = params.getTransactionSize();
+
+ long start = System.currentTimeMillis();
+ for(int i=0; i < count; i++ )
+ {
+ Message msg = getNextMessage();
+ msg.setJMSTimestamp(System.currentTimeMillis());
+ producer.send(msg);
+ if ( transacted && ((i+1) % tranSize == 0))
+ {
+ session.commit();
+ }
+ }
+ long time = System.currentTimeMillis() - start;
+ double rate = ((double)count/(double)time)*1000;
+ System.out.println(new StringBuilder("Producer rate: ").
+ append(df.format(rate)).
+ append(" msg/sec").
+ toString());
+ }
+
+ public void waitForCompletion() throws Exception
+ {
+ MessageConsumer tmp = session.createConsumer(feedbackDest);
+ Message msg = session.createTextMessage("End");
+ msg.setJMSReplyTo(feedbackDest);
+ producer.send(msg);
+
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.receive();
+
+ if (params.isTransacted())
+ {
+ session.commit();
+ }
+
+ tmp.close();
+ System.out.println("Consumer has completed the test......");
+ }
+
+ public void tearDown() throws Exception
+ {
+ producer.close();
+ session.close();
+ con.close();
+ }
+
+ public void test()
+ {
+ try
+ {
+ setUp();
+ warmup();
+ startTest();
+ waitForCompletion();
+ tearDown();
+ }
+ catch(Exception e)
+ {
+ handleError(e,"Error when running test");
+ }
+ }
+
+
+ public static void main(String[] args)
+ {
+ PerfProducer prod = new PerfProducer();
+ prod.test();
+ }
+} \ No newline at end of file
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/perf/TestParams.java b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/TestParams.java
new file mode 100644
index 0000000000..15142cfced
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/perf/TestParams.java
@@ -0,0 +1,160 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.perf;
+
+import javax.jms.Session;
+
+public class TestParams
+{
+ private String initialContextFactory = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+ private String providerURL = System.getenv("QPID_TEST_HOME") + "/etc/jndi.properties";
+
+ private String connectionFactory = "connectionFactory";
+
+ private String transientDest = "transientQueue";
+
+ private String durableDest = "durableQueue";
+
+ private int msg_size = 512;
+
+ private int msg_type = 1; // not used yet
+
+ private boolean cacheMessage = true;
+
+ private boolean disableMessageID = false;
+
+ private boolean disableTimestamp = false;
+
+ private boolean durable = false;
+
+ private boolean transacted = false;
+
+ private int transaction_size = 1000;
+
+ private int ack_mode = Session.AUTO_ACKNOWLEDGE;
+
+ private int msg_count = 10;
+
+ private int warmup_count = 1;
+
+ public TestParams()
+ {
+ initialContextFactory = System.getProperty("java.naming.factory.initial",initialContextFactory);
+ providerURL = System.getProperty("java.naming.provider.url",providerURL);
+
+ transientDest = System.getProperty("transDest",transientDest);
+ durableDest = System.getProperty("durableDest",durableDest);
+
+ msg_size = Integer.getInteger("msg_size", 512);
+ msg_type = Integer.getInteger("msg_type",1);
+ cacheMessage = Boolean.getBoolean("cache_msg");
+ disableMessageID = Boolean.getBoolean("disableMessageID");
+ disableTimestamp = Boolean.getBoolean("disableTimestamp");
+ durable = Boolean.getBoolean("durable");
+ transacted = Boolean.getBoolean("transacted");
+ transaction_size = Integer.getInteger("trans_size",1000);
+ ack_mode = Integer.getInteger("ack_mode",Session.AUTO_ACKNOWLEDGE);
+ msg_count = Integer.getInteger("msg_count",msg_count);
+ warmup_count = Integer.getInteger("warmup_count",warmup_count);
+ }
+
+ public int getAckMode()
+ {
+ return ack_mode;
+ }
+
+ public String getConnectionFactory()
+ {
+ return connectionFactory;
+ }
+
+ public String getTransientDestination()
+ {
+ return transientDest;
+ }
+
+ public String getDurableDestination()
+ {
+ return durableDest;
+ }
+
+ public String getInitialContextFactory()
+ {
+ return initialContextFactory;
+ }
+
+ public int getMsgCount()
+ {
+ return msg_count;
+ }
+
+ public int getMsgSize()
+ {
+ return msg_size;
+ }
+
+ public int getMsgType()
+ {
+ return msg_type;
+ }
+
+ public boolean isDurable()
+ {
+ return durable;
+ }
+
+ public String getProviderURL()
+ {
+ return providerURL;
+ }
+
+ public boolean isTransacted()
+ {
+ return transacted;
+ }
+
+ public int getTransactionSize()
+ {
+ return transaction_size;
+ }
+
+ public int getWarmupCount()
+ {
+ return warmup_count;
+ }
+
+ public boolean isCacheMessage()
+ {
+ return cacheMessage;
+ }
+
+ public boolean isDisableMessageID()
+ {
+ return disableMessageID;
+ }
+
+ public boolean isDisableTimestamp()
+ {
+ return disableTimestamp;
+ }
+
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/BaseTest.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/BaseTest.java
new file mode 100644
index 0000000000..0c3a17b3d8
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/BaseTest.java
@@ -0,0 +1,152 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.testkit.MessageFactory;
+
+public class BaseTest
+{
+ protected String host = "127.0.0.1";
+ protected int msg_size = 100;
+ protected int msg_count = 10;
+ protected int session_count = 1;
+ protected boolean durable = false;
+ protected String queue_name = "message_queue";
+ protected String exchange_name = "amq.direct";
+ protected String routing_key = "routing_key";
+ protected String contentType = "application/octet-stream";
+ protected int port = 5672;
+ protected String url;
+ protected Message[] msgArray;
+
+ protected AMQConnection con;
+ protected Destination dest = null;
+ protected DateFormat df = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss");
+ protected NumberFormat nf = new DecimalFormat("##.00");
+
+ public BaseTest()
+ {
+ host = System.getProperty("host", "127.0.0.1");
+ port = Integer.getInteger("port", 5672);
+ msg_size = Integer.getInteger("msg_size", 100);
+ msg_count = Integer.getInteger("msg_count", 10);
+ session_count = Integer.getInteger("session_count", 1);
+ durable = Boolean.getBoolean("durable");
+ queue_name = System.getProperty("queue_name", "message_queue");
+ exchange_name = System.getProperty("exchange_name", "amq.direct");
+ routing_key = System.getProperty("routing_key", "routing_key");
+ contentType = System.getProperty("content_type","application/octet-stream");
+
+
+
+ url = "amqp://username:password@topicClientid/test?brokerlist='tcp://" + host + ":" + port + "'";
+ }
+
+ public void setUp()
+ {
+ try
+ {
+ con = new AMQConnection(url);
+ con.start();
+
+
+ if (exchange_name.equals("amq.topic"))
+ {
+ dest = new AMQTopic(new AMQShortString(exchange_name),
+ new AMQShortString(routing_key),
+ false, //auto-delete
+ null, //queue name
+ durable);
+ }
+ else
+ {
+ dest = new AMQQueue(new AMQShortString(exchange_name),
+ new AMQShortString(routing_key),
+ new AMQShortString(queue_name),
+ false, //exclusive
+ false, //auto-delete
+ durable);
+ }
+
+ // Create the session to setup the messages
+ Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ if (msg_size == -1)
+ {
+ // This creates an array of 1000 messages from 500-1500 bytes
+ // During the tests a message will be picked randomly
+ msgArray = new Message[1000];
+ for (int i = 0; i < 1000; i++)
+ {
+ Message msg = (contentType.equals("text/plain")) ?
+ MessageFactory.createTextMessage(session,500 + i) :
+ MessageFactory.createBytesMessage(session, 500 + i);
+ msg.setJMSDeliveryMode((durable) ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+ msgArray[i] = msg;
+ }
+ }
+ else
+ {
+ Message msg = (contentType.equals("text/plain")) ?
+ MessageFactory.createTextMessage(session, msg_size):
+ MessageFactory.createBytesMessage(session, msg_size);
+ msg.setJMSDeliveryMode((durable) ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+ msgArray = new Message[]
+ { msg };
+ }
+
+ session.close();
+
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Error while setting up the test");
+ }
+ }
+
+ public void handleError(Exception e,String msg)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(msg);
+ sb.append(" @ ");
+ sb.append(df.format(new Date(System.currentTimeMillis())));
+ sb.append(" ");
+ sb.append(e.getMessage());
+ System.err.println(sb.toString());
+ e.printStackTrace();
+ }
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedConsumer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedConsumer.java
new file mode 100644
index 0000000000..a91d9e7e85
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedConsumer.java
@@ -0,0 +1,153 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+/**
+ * Test Description
+ * ================
+ * The difference between this test and the
+ * LongDurationConsumer is that each Session runs
+ * in it's own Thread and the ability to receive
+ * messages transactionally.
+ *
+ * All consumers will still share the same destination.
+ *
+ */
+public class MultiThreadedConsumer extends BaseTest
+{
+ protected final boolean transacted;
+
+ public MultiThreadedConsumer()
+ {
+ super();
+ transacted = Boolean.getBoolean("transacted");
+ // needed only to calculate throughput.
+ // If msg_count is different set it via -Dmsg_count
+ msg_count = 10;
+ }
+
+ /**
+ * Creates a Session and a consumer that runs in its
+ * own thread.
+ * It can also consume transactionally.
+ *
+ */
+ public void test()
+ {
+ try
+ {
+ for (int i = 0; i < session_count; i++)
+ {
+
+ final Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Thread t = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ MessageConsumer consumer = session.createConsumer(dest);
+
+ consumer.setMessageListener(new MessageListener()
+ {
+
+ private boolean startIteration = true;
+ private long startTime = 0;
+ private long iterations = 0;
+
+ public void onMessage(Message m)
+ {
+ try
+ {
+ long now = System.currentTimeMillis();
+ if (startIteration)
+ {
+ startTime = m.getJMSTimestamp();
+ startIteration = false;
+ }
+
+ if (m instanceof TextMessage && ((TextMessage) m).getText().equals("End"))
+ {
+ startIteration = true;
+ long totalIterationTime = now - startTime;
+ double throughput = ((double)msg_count/(double)totalIterationTime) * 1000;
+ long latencySample = now - m.getJMSTimestamp();
+ iterations++;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(iterations).append(",").
+ append(nf.format(throughput)).append(",").append(latencySample);
+
+ System.out.println(sb.toString());
+
+ MessageProducer temp = session.createProducer(m.getJMSReplyTo());
+ Message controlMsg = session.createTextMessage();
+ temp.send(controlMsg);
+ if (transacted)
+ {
+ session.commit();
+ }
+ temp.close();
+ }
+ }
+ catch (JMSException e)
+ {
+ handleError(e,"Exception receiving messages");
+ }
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception creating a consumer");
+ }
+
+ }
+
+ });
+ t.setName("session-" + i);
+ t.start();
+ } // for loop
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception while setting up the test");
+ }
+
+ }
+
+ public static void main(String[] args)
+ {
+ MultiThreadedConsumer test = new MultiThreadedConsumer();
+ test.setUp();
+ test.test();
+ }
+
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedProducer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedProducer.java
new file mode 100644
index 0000000000..279e5ea0bf
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/MultiThreadedProducer.java
@@ -0,0 +1,166 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import java.util.Random;
+import java.util.UUID;
+
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.framing.AMQShortString;
+
+/**
+ * Test Description
+ * ================
+ *
+ * This test creats x number of sessions, where each session
+ * runs in it's own thread. Each session creates a producer
+ * and it's own feedback queue.
+ *
+ * A producer will send n-1 messages, followed by the n-th
+ * message which contains "End" in it's payload to signal
+ * that this is the last message message in the sequence.
+ * The end message has the feedback queue as it's replyTo.
+ * It will then listen on the feedback queue waiting for the
+ * confirmation and then sleeps for 1000 ms before proceeding
+ * with the next n messages.
+ *
+ * This hand shaking mechanism ensures that all of the
+ * messages sent are consumed by some consumer. This prevents
+ * the producers from saturating the broker especially when
+ * the consumers are slow.
+ *
+ * All producers send to a single destination
+ * If using transactions it's best to use smaller message count
+ * as the test only commits after sending all messages in a batch.
+ *
+ */
+
+public class MultiThreadedProducer extends SimpleProducer
+{
+ protected final boolean transacted;
+
+ public MultiThreadedProducer()
+ {
+ super();
+ transacted = Boolean.getBoolean("transacted");
+ }
+
+ public void test()
+ {
+ try
+ {
+ final int msg_count_per_session = msg_count/session_count;
+
+ for (int i = 0; i < session_count; i++)
+ {
+ final Session session = con.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
+ Thread t = new Thread(new Runnable()
+ {
+ private Random gen = new Random();
+
+ private Message getNextMessage()
+ {
+ if (msg_size == -1)
+ {
+ int index = gen.nextInt(1000);
+ return msgArray[index];
+ }
+ else
+ {
+ return msgArray[0];
+ }
+ }
+
+ public void run()
+ {
+ try
+ {
+ MessageProducer prod = session.createProducer(dest);
+ // this will ensure that the producer will not overun the consumer.
+ feedbackQueue = new AMQQueue(new AMQShortString("amq.direct"), new AMQShortString(UUID
+ .randomUUID().toString()), new AMQShortString("control"));
+
+ MessageConsumer feedbackConsumer = session.createConsumer(feedbackQueue);
+
+ while (true)
+ {
+ for (int i = 0; i < msg_count_per_session; i++)
+ {
+ Message msg = getNextMessage();
+ msg.setJMSMessageID("ID:" + UUID.randomUUID());
+ prod.send(msg);
+ }
+
+ TextMessage m = session.createTextMessage("End");
+ m.setJMSReplyTo(feedbackQueue);
+ prod.send(m);
+
+ if (transacted)
+ {
+ session.commit();
+ }
+
+ System.out.println(df.format(System.currentTimeMillis()));
+ feedbackConsumer.receive();
+ if (transacted)
+ {
+ session.commit();
+ }
+ Thread.sleep(1000);
+ }
+
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception in producing message");
+ }
+
+ }
+
+ });
+ t.setName("session-" + i);
+ t.start();
+
+ }
+
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception while setting up the test");
+ }
+
+ }
+
+ public static void main(String[] args)
+ {
+ MultiThreadedProducer test = new MultiThreadedProducer();
+ test.setUp();
+ test.test();
+ }
+
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java
new file mode 100644
index 0000000000..c33f9ffbf2
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/ResourceLeakTest.java
@@ -0,0 +1,138 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import javax.jms.BytesMessage;
+import javax.jms.Destination;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.framing.AMQShortString;
+
+/**
+ * Test Description
+ * ================
+ * This test will open x number of connections where each
+ * connection will create a session and a producer/consumer pair,
+ * and then send configurable no of messages.
+ * It will them sleep for configurable time interval and
+ * tear down the connections/sessions/consumers.
+ * It will then repeat the process again until the test is stopped.
+ *
+ * Purpose of the test
+ * ===================
+ * To find if the broker has leaks when cleaning resources.
+ * To find if the client has leaks with resources.
+ */
+public class ResourceLeakTest extends BaseTest
+{
+ protected int connection_count = 10;
+ protected long connection_idle_time = 5000;
+
+ public ResourceLeakTest()
+ {
+ super();
+ connection_count = Integer.getInteger("con_count",10);
+ connection_idle_time = Long.getLong("con_idle_time", 5000);
+ }
+
+ public void test()
+ {
+ try
+ {
+
+ AMQConnection[] cons = new AMQConnection[connection_count];
+ Session[] sessions = new Session[connection_count];
+ MessageConsumer[] msgCons = new MessageConsumer[connection_count];
+ MessageProducer [] msgProds = new MessageProducer[connection_count];
+ Destination dest = new AMQQueue(new AMQShortString(exchange_name),
+ new AMQShortString(routing_key),
+ new AMQShortString(queue_name),
+ true, //exclusive
+ true // auto delete
+ );
+
+ while (true)
+ {
+ for (int i = 0; i < connection_count; i++)
+ {
+ AMQConnection con = new AMQConnection(url);
+ con.start();
+ cons[i] = con;
+ Session ssn = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ sessions[i] = ssn;
+ MessageConsumer msgCon = ssn.createConsumer(dest);
+ msgCons[i] = msgCon;
+ MessageProducer msgProd = ssn.createProducer(dest);
+ msgProds[i] = msgProd;
+
+ BytesMessage msg = ssn.createBytesMessage();
+ msg.writeBytes("Test Msg".getBytes());
+
+ for (int j = 0; j < msg_count;j++)
+ {
+ msgProd.send(msg);
+ }
+
+ int j = 0;
+ while (j < msg_count)
+ {
+ msgCon.receive();
+ j++;
+ }
+ }
+ System.out.println(df.format(System.currentTimeMillis()));
+ Thread.sleep(connection_idle_time);
+
+ try
+ {
+ for (int i = 0; i < connection_count; i++)
+ {
+ msgCons[i].close();
+ msgProds[i].close();
+ sessions[i].close();
+ cons[i].close();
+ }
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception closing resources");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception in setting up the test");
+ }
+
+ }
+
+ public static void main(String[] args)
+ {
+ ResourceLeakTest test = new ResourceLeakTest();
+ test.test();
+ }
+
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleConsumer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleConsumer.java
new file mode 100644
index 0000000000..b3eb97dafe
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleConsumer.java
@@ -0,0 +1,134 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+/**
+ * Test Description
+ * ================
+ * This test will create x number of sessions.
+ * Each session will have it's own consumer.
+ * Once a consumer receives the "End" message it
+ * will send a message to the destination indicated
+ * by the replyTo field in the End message.
+ * This will signal the producer that all the previous
+ * messages have been consumed. The producer will
+ * then start sending messages again.
+ *
+ * This prevents the producer from overruning the
+ * consumer.
+ * *
+ * All consumers share a single destination
+ *
+ */
+
+public class SimpleConsumer extends BaseTest
+{
+ public SimpleConsumer()
+ {
+ super();
+ //needed only to calculate throughput.
+ // If msg_count is different set it via -Dmsg_count
+ msg_count = 10;
+ }
+
+ public void test()
+ {
+ try
+ {
+ final Session[] sessions = new Session[session_count];
+ MessageConsumer[] cons = new MessageConsumer[session_count];
+
+ for (int i = 0; i < session_count; i++)
+ {
+ sessions[i] = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ cons[i] = sessions[i].createConsumer(dest);
+ cons[i].setMessageListener(new MessageListener()
+ {
+
+ private boolean startIteration = true;
+ private long startTime = 0;
+ private long iterations = 0;
+
+ public void onMessage(Message m)
+ {
+ try
+ {
+ long now = System.currentTimeMillis();
+ if (startIteration)
+ {
+ startTime = m.getJMSTimestamp();
+ startIteration = false;
+ }
+
+ if (m instanceof TextMessage && ((TextMessage) m).getText().equals("End"))
+ {
+
+ long totalIterationTime = now - startTime;
+ startIteration = true;
+ double throughput = ((double)msg_count/(double)totalIterationTime) * 1000;
+ long latencySample = now - m.getJMSTimestamp();
+ iterations++;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(iterations).append(",").
+ append(nf.format(throughput)).append(",").append(latencySample);
+
+ System.out.println(sb.toString());
+
+ MessageProducer temp = sessions[0].createProducer(m.getJMSReplyTo());
+ Message controlMsg = sessions[0].createTextMessage();
+ temp.send(controlMsg);
+ temp.close();
+ }
+ }
+ catch (JMSException e)
+ {
+ handleError(e,"Exception when receiving the message");
+ }
+ }
+ });
+ }
+
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception when setting up the consumers");
+ }
+
+ }
+
+ public static void main(String[] args)
+ {
+ SimpleConsumer test = new SimpleConsumer();
+ test.setUp();
+ test.test();
+ }
+
+}
diff --git a/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleProducer.java b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleProducer.java
new file mode 100644
index 0000000000..1080092536
--- /dev/null
+++ b/java/testkit/src/main/java/org/apache/qpid/testkit/soak/SimpleProducer.java
@@ -0,0 +1,146 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.testkit.soak;
+
+
+import java.util.Random;
+import java.util.UUID;
+
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.framing.AMQShortString;
+
+/**
+ * Test Description
+ * ================
+ * This test will send n-1 messages, followed by the n-th
+ * message which contains "End" in it's payload to signal
+ * that this is the last message message in the sequence.
+ * The end message has the feedback queue as it's replyTo.
+ * It will then listen on the feedback queue waiting for the
+ * confirmation and then sleeps for 1000 ms before proceeding
+ * with the next n messages.
+ *
+ * This hand shaking mechanism ensures that all of the
+ * messages sent are consumed by some consumer. This prevents
+ * the producers from saturating the broker especially when
+ * the consumers are slow.
+ *
+ * It creates a producer per session.
+ * If session_count is > 1 it will round robin the messages
+ * btw the producers.
+ *
+ * All producers send to a single destination
+ *
+ */
+
+public class SimpleProducer extends BaseTest
+{
+ protected Destination feedbackQueue;
+ Random gen = new Random();
+
+ public SimpleProducer()
+ {
+ super();
+ }
+
+ protected Message getNextMessage()
+ {
+ if (msg_size == -1)
+ {
+ int index = gen.nextInt(1000);
+ return msgArray[index];
+ }
+ else
+ {
+ return msgArray[0];
+ }
+ }
+
+ public void test()
+ {
+ try
+ {
+ Session[] sessions = new Session[session_count];
+ MessageProducer[] prods = new MessageProducer[session_count];
+
+ for (int i = 0; i < session_count; i++)
+ {
+ sessions[i] = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ prods[i] = sessions[i].createProducer(dest);
+ }
+
+ // this will ensure that the producer will not overun the consumer.
+ feedbackQueue = new AMQQueue(new AMQShortString("amq.direct"),
+ new AMQShortString(UUID.randomUUID().toString()),
+ new AMQShortString("control"));
+
+ MessageConsumer feedbackConsumer = sessions[0].createConsumer(feedbackQueue);
+
+ int prod_pointer = 0;
+ boolean multi_session = session_count > 1 ? true : false;
+
+ while (true)
+ {
+ for (int i = 0; i < msg_count - 1; i++)
+ {
+ Message msg = getNextMessage();
+ msg.setJMSTimestamp(System.currentTimeMillis());
+ prods[prod_pointer].send(msg);
+ if (multi_session)
+ {
+ prod_pointer++;
+ if (prod_pointer == session_count)
+ {
+ prod_pointer = 0;
+ }
+ }
+ }
+
+ TextMessage m = sessions[0].createTextMessage("End");
+ m.setJMSReplyTo(feedbackQueue);
+ prods[prod_pointer].send(m);
+ System.out.println(df.format(System.currentTimeMillis()));
+ feedbackConsumer.receive();
+ Thread.sleep(1000);
+ }
+ }
+ catch (Exception e)
+ {
+ handleError(e,"Exception while setting up the producer");
+ }
+
+ }
+
+ public static void main(String[] args)
+ {
+ SimpleProducer test = new SimpleProducer();
+ test.setUp();
+ test.test();
+ }
+
+}
diff --git a/java/tools/bin/qpid-bench b/java/tools/bin/qpid-bench
new file mode 100644
index 0000000000..21b092563a
--- /dev/null
+++ b/java/tools/bin/qpid-bench
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+if [ -z "$QPID_HOME" ]; then
+ export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+ export PATH=${PATH}:${QPID_HOME}/bin
+fi
+
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-incubating.jar
+
+# Set other variables used by the qpid-run script before calling
+export JAVA=java \
+ JAVA_VM=-server \
+ JAVA_MEM=-Xmx1024m \
+ QPID_CLASSPATH=$QPID_LIBS
+
+. qpid-run org.apache.qpid.tools.QpidBench "$@"
diff --git a/java/tools/build.xml b/java/tools/build.xml
new file mode 100644
index 0000000000..7cd1b1172c
--- /dev/null
+++ b/java/tools/build.xml
@@ -0,0 +1,27 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<project name="Qpid Tools" default="build">
+
+ <property name="module.depends" value="client common"/>
+
+ <import file="../module.xml"/>
+
+</project>
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/JNDICheck.java b/java/tools/src/main/java/org/apache/qpid/tools/JNDICheck.java
new file mode 100644
index 0000000000..9ead0c19f2
--- /dev/null
+++ b/java/tools/src/main/java/org/apache/qpid/tools/JNDICheck.java
@@ -0,0 +1,200 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.tools;
+
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.jms.FailoverPolicy;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.LinkedList;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileInputStream;
+
+public class JNDICheck
+{
+ private static final String QUEUE = "queue.";
+ private static final String TOPIC = "topic.";
+ private static final String DESTINATION = "destination.";
+ private static final String CONNECTION_FACTORY = "connectionfactory.";
+
+ public static void main(String[] args)
+ {
+
+ if (args.length != 1)
+ {
+ usage();
+ }
+
+ String propertyFile = args[0];
+
+ new JNDICheck(propertyFile);
+ }
+
+ private static void usage()
+ {
+ exit("Usage: JNDICheck <JNDI Config file>", 0);
+ }
+
+ private static void exit(String message, int exitCode)
+ {
+ System.err.println(message);
+ System.exit(exitCode);
+ }
+
+ private static String JAVA_NAMING = "java.naming.factory.initial";
+
+ Context _context = null;
+ Hashtable _environment = null;
+
+ public JNDICheck(String propertyFile)
+ {
+
+ // Load JNDI properties
+ Properties properties = new Properties();
+
+ try
+ {
+ properties.load(new FileInputStream(new File(propertyFile)));
+ }
+ catch (IOException e)
+ {
+ exit("Unable to open property file:" + propertyFile + ". Due to:" + e.getMessage(), 1);
+ }
+
+ //Create the initial context
+ try
+ {
+
+ System.setProperty(JAVA_NAMING, properties.getProperty(JAVA_NAMING));
+
+ _context = new InitialContext(properties);
+
+ _environment = _context.getEnvironment();
+
+ Enumeration keys = _environment.keys();
+
+ List<String> queues = new LinkedList<String>();
+ List<String> topics = new LinkedList<String>();
+ List<String> destinations = new LinkedList<String>();
+ List<String> connectionFactories = new LinkedList<String>();
+
+ while (keys.hasMoreElements())
+ {
+ String key = keys.nextElement().toString();
+
+ if (key.startsWith(QUEUE))
+ {
+ queues.add(key);
+ }
+ else if (key.startsWith(TOPIC))
+ {
+ topics.add(key);
+ }
+ else if (key.startsWith(DESTINATION))
+ {
+ destinations.add(key);
+ }
+ else if (key.startsWith(CONNECTION_FACTORY))
+ {
+ connectionFactories.add(key);
+ }
+ }
+
+ printHeader(propertyFile);
+ printEntries(QUEUE, queues);
+ printEntries(TOPIC, topics);
+ printEntries(DESTINATION, destinations);
+ printEntries(CONNECTION_FACTORY, connectionFactories);
+
+ }
+ catch (NamingException e)
+ {
+ exit("Unable to load JNDI Context due to:" + e.getMessage(), 1);
+ }
+
+ }
+
+ private void printHeader(String file)
+ {
+ print("JNDI file :" + file);
+ }
+
+ private void printEntries(String type, List<String> list)
+ {
+ if (list.size() > 0)
+ {
+ String name = type.substring(0, 1).toUpperCase() + type.substring(1, type.length() - 1);
+ print(name + " elements in file:");
+ printList(list);
+ print("");
+ }
+ }
+
+ private void printList(List<String> list)
+ {
+ for (String item : list)
+ {
+ String key = item.substring(item.indexOf('.') + 1);
+
+ try
+ {
+ print(key, _context.lookup(key));
+ }
+ catch (NamingException e)
+ {
+ exit("Error: item " + key + " no longer in context.", 1);
+ }
+ }
+ }
+
+ private void print(String key, Object object)
+ {
+ if (object instanceof AMQDestination)
+ {
+ print(key + ":" + object);
+ }
+ else if (object instanceof AMQConnectionFactory)
+ {
+ AMQConnectionFactory factory = (AMQConnectionFactory) object;
+ print(key + ":Connection");
+ print("ConnectionURL:");
+ print(factory.getConnectionURL().toString());
+ print("FailoverPolicy");
+ print(new FailoverPolicy(factory.getConnectionURL()).toString());
+ print("");
+ }
+ }
+
+ private void print(String msg)
+ {
+ System.out.println(msg);
+ }
+
+}
diff --git a/java/tools/src/main/java/org/apache/qpid/tools/QpidBench.java b/java/tools/src/main/java/org/apache/qpid/tools/QpidBench.java
new file mode 100644
index 0000000000..181cf427d1
--- /dev/null
+++ b/java/tools/src/main/java/org/apache/qpid/tools/QpidBench.java
@@ -0,0 +1,885 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.tools;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import javax.jms.*;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.transport.*;
+import org.apache.qpid.transport.network.io.IoTransport;
+import org.apache.qpid.util.UUIDGen;
+import org.apache.qpid.util.UUIDs;
+
+import static org.apache.qpid.tools.QpidBench.Mode.*;
+
+/**
+ * QpidBench
+ *
+ */
+
+public class QpidBench
+{
+
+ static enum Mode
+ {
+ PUBLISH, CONSUME, BOTH
+ }
+
+ private static class Options
+ {
+ private StringBuilder usage = new StringBuilder("qpid-bench <options>");
+
+ void usage(String name, String description, Object def)
+ {
+ String defval = "";
+ if (def != null)
+ {
+ defval = String.format(" (%s)", def);
+ }
+ usage.append(String.format("\n %-15s%-14s %s", name, defval, description));
+ }
+
+ public String broker = "localhost";
+ public int port = 5672;
+ public long count = 1000000;
+ public long window = 100000;
+ public long sample = window;
+ public int size = 1024;
+ public Mode mode = BOTH;
+ public boolean timestamp = false;
+ public boolean message_id = false;
+ public boolean message_cache = false;
+ public boolean persistent = false;
+ public boolean jms_publish = false;
+ public boolean jms_consume = false;
+ public boolean help = false;
+
+ {
+ usage("-b, --broker", "the broker hostname", broker);
+ }
+
+ public void parse__broker(String b)
+ {
+ this.broker = b;
+ }
+
+ public void parse_b(String b)
+ {
+ parse__broker(b);
+ }
+
+ {
+ usage("-p, --port", "the broker port", port);
+ }
+
+ public void parse__port(String p)
+ {
+ this.port = Integer.parseInt(p);
+ }
+
+ public void parse_p(String p)
+ {
+ parse__port(p);
+ }
+
+ {
+ usage("-c, --count", "the number of messages to send/receive, 0 means no limit", count);
+ }
+
+ public void parse__count(String c)
+ {
+ this.count = Long.parseLong(c);
+ }
+
+ public void parse_c(String c)
+ {
+ parse__count(c);
+ }
+
+ {
+ usage("-w, --window", "the number of messages to send before blocking, 0 disables", window);
+ }
+
+ public void parse__window(String w)
+ {
+ this.window = Long.parseLong(w);
+ }
+
+ public void parse_w(String w)
+ {
+ parse__window(w);
+ }
+
+ {
+ usage("--sample", "print stats after this many messages, 0 disables", sample);
+ }
+
+ public void parse__sample(String s)
+ {
+ this.sample = Long.parseLong(s);
+ }
+
+ {
+ usage("-i, --interval", "sets both --window and --sample", window);
+ }
+
+ public void parse__interval(String i)
+ {
+ this.window = Long.parseLong(i);
+ this.sample = window;
+ }
+
+ public void parse_i(String i)
+ {
+ parse__interval(i);
+ }
+
+ {
+ usage("-s, --size", "the message size", size);
+ }
+
+ public void parse__size(String s)
+ {
+ this.size = Integer.parseInt(s);
+ }
+
+ public void parse_s(String s)
+ {
+ parse__size(s);
+ }
+
+ {
+ usage("-m, --mode", "one of publish, consume, or both", mode);
+ }
+
+ public void parse__mode(String m)
+ {
+ if (m.equalsIgnoreCase("publish"))
+ {
+ this.mode = PUBLISH;
+ }
+ else if (m.equalsIgnoreCase("consume"))
+ {
+ this.mode = CONSUME;
+ }
+ else if (m.equalsIgnoreCase("both"))
+ {
+ this.mode = BOTH;
+ }
+ else
+ {
+ throw new IllegalArgumentException
+ ("must be one of 'publish', 'consume', or 'both'");
+ }
+ }
+
+ public void parse_m(String m)
+ {
+ parse__mode(m);
+ }
+
+ {
+ usage("--timestamp", "set timestamps on each message if true", timestamp);
+ }
+
+ public void parse__timestamp(String t)
+ {
+ this.timestamp = Boolean.parseBoolean(t);
+ }
+
+ {
+ usage("--mesage-id", "set the message-id on each message if true", message_id);
+ }
+
+ public void parse__message_id(String m)
+ {
+ this.message_id = Boolean.parseBoolean(m);
+ }
+
+ {
+ usage("--message-cache", "reuse the same message for each send if true", message_cache);
+ }
+
+ public void parse__message_cache(String c)
+ {
+ this.message_cache = Boolean.parseBoolean(c);
+ }
+
+ {
+ usage("--persistent", "set the delivery-mode to persistent if true", persistent);
+ }
+
+ public void parse__persistent(String p)
+ {
+ this.persistent = Boolean.parseBoolean(p);
+ }
+
+ {
+ usage("--jms-publish", "use the jms client for publish", jms_publish);
+ }
+
+ public void parse__jms_publish(String jp)
+ {
+ this.jms_publish = Boolean.parseBoolean(jp);
+ }
+
+ {
+ usage("--jms-consume", "use the jms client for consume", jms_consume);
+ }
+
+ public void parse__jms_consume(String jc)
+ {
+ this.jms_consume = Boolean.parseBoolean(jc);
+ }
+
+ {
+ usage("--jms", "sets both --jms-publish and --jms-consume", false);
+ }
+
+ public void parse__jms(String j)
+ {
+ this.jms_publish = this.jms_consume = Boolean.parseBoolean(j);
+ }
+
+ {
+ usage("-h, --help", "prints this message", null);
+ }
+
+ public void parse__help()
+ {
+ this.help = true;
+ }
+
+ public void parse_h()
+ {
+ parse__help();
+ }
+
+ public String parse(String ... args)
+ {
+ Class klass = getClass();
+ List<String> arguments = new ArrayList<String>();
+ for (int i = 0; i < args.length; i++)
+ {
+ String option = args[i];
+
+ if (!option.startsWith("-"))
+ {
+ arguments.add(option);
+ continue;
+ }
+
+ String method = "parse" + option.replace('-', '_');
+ try
+ {
+ try
+ {
+ Method parser = klass.getMethod(method);
+ parser.invoke(this);
+ }
+ catch (NoSuchMethodException e)
+ {
+ try
+ {
+ Method parser = klass.getMethod(method, String.class);
+
+ String value = null;
+ if (i + 1 < args.length)
+ {
+ value = args[i+1];
+ i++;
+ }
+ else
+ {
+ return option + " requires a value";
+ }
+
+ parser.invoke(this, value);
+ }
+ catch (NoSuchMethodException e2)
+ {
+ return "no such option: " + option;
+ }
+ }
+ }
+ catch (InvocationTargetException e)
+ {
+ Throwable t = e.getCause();
+ return String.format
+ ("error parsing %s: %s: %s", option, t.getClass().getName(),
+ t.getMessage());
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException
+ ("unable to access parse method: " + option, e);
+ }
+ }
+
+ return parseArguments(arguments);
+ }
+
+ public String parseArguments(List<String> arguments)
+ {
+ if (arguments.size() > 0)
+ {
+ String args = arguments.toString();
+ return "unrecognized arguments: " + args.substring(1, args.length() - 1);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public String toString()
+ {
+ Class klass = getClass();
+ Field[] fields = klass.getFields();
+ StringBuilder str = new StringBuilder();
+ for (int i = 0; i < fields.length; i++)
+ {
+ if (i > 0)
+ {
+ str.append("\n");
+ }
+
+ String name = fields[i].getName();
+ str.append(name);
+ str.append(" = ");
+ Object value;
+ try
+ {
+ value = fields[i].get(this);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException
+ ("unable to access field: " + name, e);
+ }
+ str.append(value);
+ }
+
+ return str.toString();
+ }
+ }
+
+ public static final void main(String[] args) throws Exception
+ {
+ final Options opts = new Options();
+ String error = opts.parse(args);
+ if (error != null)
+ {
+ System.err.println(error);
+ System.exit(-1);
+ return;
+ }
+
+ if (opts.help)
+ {
+ System.out.println(opts.usage);
+ return;
+ }
+
+ System.out.println(opts);
+
+ switch (opts.mode)
+ {
+ case CONSUME:
+ case BOTH:
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ if (opts.jms_consume)
+ {
+ jms_consumer(opts);
+ }
+ else
+ {
+ native_consumer(opts);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }.start();
+ break;
+ }
+
+ switch (opts.mode)
+ {
+ case PUBLISH:
+ case BOTH:
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ if (opts.jms_publish)
+ {
+ jms_publisher(opts);
+ }
+ else
+ {
+ native_publisher(opts);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+ }.start();
+ break;
+ }
+ }
+
+ private static enum Column
+ {
+ LEFT, RIGHT
+ }
+
+ private static final void sample(Options opts, Column col, String name, long count,
+ long start, long time, long lastTime)
+ {
+ String pfx = "";
+ String sfx = "";
+ if (opts.mode == BOTH)
+ {
+ if (col == Column.RIGHT)
+ {
+ pfx = " -- ";
+ }
+ else
+ {
+ sfx = " --";
+ }
+ }
+
+ if (count == 0)
+ {
+ String stats = String.format("%s: %tc", name, start);
+ System.out.println(String.format("%s%-36s%s", pfx, stats, sfx));
+ return;
+ }
+
+ double cumulative = 1000 * (double) count / (double) (time - start);
+ double interval = 1000 * ((double) opts.sample / (double) (time - lastTime));
+
+ String stats = String.format
+ ("%s: %d %.2f %.2f", name, count, cumulative, interval);
+ System.out.println(String.format("%s%-36s%s", pfx, stats, sfx));
+ }
+
+ private static final javax.jms.Connection getJMSConnection(Options opts) throws Exception
+ {
+ String url = String.format
+ ("amqp://guest:guest@clientid/test?brokerlist='tcp://%s:%d'",
+ opts.broker, opts.port);
+ return new AMQConnection(url);
+ }
+
+ private static final void jms_publisher(Options opts) throws Exception
+ {
+ javax.jms.Connection conn = getJMSConnection(opts);
+
+ javax.jms.Session ssn = conn.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
+ Destination dest = ssn.createQueue("test-queue");
+ Destination echo_dest = ssn.createQueue("echo-queue");
+ MessageProducer prod = ssn.createProducer(dest);
+ MessageConsumer cons = ssn.createConsumer(echo_dest);
+ prod.setDisableMessageID(!opts.message_id);
+ prod.setDisableMessageTimestamp(!opts.timestamp);
+ prod.setDeliveryMode(opts.persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ StringBuilder str = new StringBuilder();
+ for (int i = 0; i < opts.size; i++)
+ {
+ str.append((char) (i % 128));
+ }
+
+ String body = str.toString();
+
+ TextMessage cached = ssn.createTextMessage();
+ cached.setText(body);
+
+ conn.start();
+
+ long count = 0;
+ long lastTime = 0;
+ long start = System.currentTimeMillis();
+ while (opts.count == 0 || count < opts.count)
+ {
+ if (opts.window > 0 && (count % opts.window) == 0 && count > 0)
+ {
+ Message echo = cons.receive();
+ }
+
+ if (opts.sample > 0 && (count % opts.sample) == 0)
+ {
+ long time = System.currentTimeMillis();
+ sample(opts, Column.LEFT, "JP", count, start, time, lastTime);
+ lastTime = time;
+ }
+
+ TextMessage m;
+ if (opts.message_cache)
+ {
+ m = cached;
+ }
+ else
+ {
+ m = ssn.createTextMessage();
+ m.setText(body);
+ }
+
+ prod.send(m);
+ count++;
+ }
+
+ conn.close();
+ }
+
+ private static final void jms_consumer(final Options opts) throws Exception
+ {
+ final javax.jms.Connection conn = getJMSConnection(opts);
+ javax.jms.Session ssn = conn.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
+ Destination dest = ssn.createQueue("test-queue");
+ Destination echo_dest = ssn.createQueue("echo-queue");
+ MessageConsumer cons = ssn.createConsumer(dest);
+ final MessageProducer prod = ssn.createProducer(echo_dest);
+ prod.setDisableMessageID(true);
+ prod.setDisableMessageTimestamp(true);
+ prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+ final TextMessage echo = ssn.createTextMessage();
+ echo.setText("ECHO");
+
+ final Object done = new Object();
+ cons.setMessageListener(new MessageListener()
+ {
+ private long count = 0;
+ private long lastTime = 0;
+ private long start;
+
+ public void onMessage(Message m)
+ {
+ if (count == 0)
+ {
+ start = System.currentTimeMillis();
+ }
+
+ try
+ {
+ boolean sample = opts.sample > 0 && (count % opts.sample) == 0;
+ long time = sample ? System.currentTimeMillis() : 0;
+
+ if (opts.window > 0 && (count % opts.window) == 0)
+ {
+ prod.send(echo);
+ }
+
+ if (sample)
+ {
+ sample(opts, Column.RIGHT, "JC", count, start, time, lastTime);
+ lastTime = time;
+ }
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException(e);
+ }
+ count++;
+
+ if (opts.count > 0 && count >= opts.count)
+ {
+ synchronized (done)
+ {
+ done.notify();
+ }
+ }
+ }
+ });
+
+ conn.start();
+ synchronized (done)
+ {
+ done.wait();
+ }
+ conn.close();
+ }
+
+ private static final org.apache.qpid.transport.Connection getConnection
+ (Options opts, final SessionDelegate delegate)
+ {
+ final Object lock = new Object();
+ org.apache.qpid.transport.Connection conn =
+ IoTransport.connect(opts.broker, opts.port,
+ new ClientDelegate()
+ {
+ public SessionDelegate getSessionDelegate()
+ {
+ return delegate;
+ }
+ public void exception(Throwable t)
+ {
+ t.printStackTrace();
+ }
+ public void closed() {}
+ @Override public void connectionOpenOk(Channel ch,
+ ConnectionOpenOk ok)
+ {
+ synchronized (lock)
+ {
+ lock.notify();
+ }
+ }
+ });
+ conn.send(new ProtocolHeader(1, 0, 10));
+
+ synchronized (lock)
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return conn;
+ }
+
+ private static final void native_publisher(Options opts) throws Exception
+ {
+ final long[] echos = { 0 };
+ org.apache.qpid.transport.Connection conn = getConnection
+ (opts,
+ new SessionDelegate() {
+ @Override public void messageTransfer
+ (org.apache.qpid.transport.Session ssn,
+ MessageTransfer mt)
+ {
+ synchronized (echos)
+ {
+ echos[0]++;
+ echos.notify();
+ }
+ ssn.processed(mt);
+ }
+ });
+
+ Channel ch = conn.getChannel(0);
+ org.apache.qpid.transport.Session ssn = new org.apache.qpid.transport.Session("spam-session".getBytes());
+ ssn.attach(ch);
+ ssn.sessionAttach(ssn.getName());
+
+ ssn.invoke(new QueueDeclare().queue("test-queue").durable(false));
+ ssn.invoke(new QueueDeclare().queue("echo-queue").durable(false));
+ ssn.invoke(new ExchangeBind().exchange("amq.direct").queue("test-queue").bindingKey("test-queue"));
+ ssn.invoke(new ExchangeBind().exchange("amq.direct").queue("echo-queue").bindingKey("echo-queue"));
+
+ MessageProperties cached_mp = new MessageProperties();
+ DeliveryProperties cached_dp = new DeliveryProperties();
+ cached_dp.setRoutingKey("test-queue");
+ cached_dp.setDeliveryMode
+ (opts.persistent ? MessageDeliveryMode.PERSISTENT : MessageDeliveryMode.NON_PERSISTENT);
+
+ int size = opts.size;
+ ByteBuffer body = ByteBuffer.allocate(size);
+ for (int i = 0; i < size; i++)
+ {
+ body.put((byte) i);
+ }
+ body.flip();
+
+ ssn.invoke(new MessageSubscribe()
+ .queue("echo-queue")
+ .destination("echo-queue")
+ .acceptMode(MessageAcceptMode.NONE)
+ .acquireMode(MessageAcquireMode.PRE_ACQUIRED));
+ ssn.messageSetFlowMode("echo-queue", MessageFlowMode.WINDOW);
+ ssn.messageFlow("echo-queue", MessageCreditUnit.MESSAGE, 0xFFFFFFFF);
+ ssn.messageFlow("echo-queue", MessageCreditUnit.BYTE, 0xFFFFFFFF);
+
+ UUIDGen gen = UUIDs.newGenerator();
+
+ long count = 0;
+ long lastTime = 0;
+ long start = System.currentTimeMillis();
+ while (opts.count == 0 || count < opts.count)
+ {
+ if (opts.window > 0 && (count % opts.window) == 0 && count > 0)
+ {
+ synchronized (echos)
+ {
+ while (echos[0] < (count/opts.window))
+ {
+ echos.wait();
+ }
+ }
+ }
+
+ if (opts.sample > 0 && (count % opts.sample) == 0)
+ {
+ long time = System.currentTimeMillis();
+ sample(opts, Column.LEFT, "NP", count, start, time, lastTime);
+ lastTime = time;
+ }
+
+ MessageProperties mp;
+ DeliveryProperties dp;
+ if (opts.message_cache)
+ {
+ mp = cached_mp;
+ dp = cached_dp;
+ }
+ else
+ {
+ mp = new MessageProperties();
+ dp = new DeliveryProperties();
+ dp.setRoutingKey("test-queue");
+ dp.setDeliveryMode
+ (opts.persistent ? MessageDeliveryMode.PERSISTENT : MessageDeliveryMode.NON_PERSISTENT);
+
+ }
+
+ if (opts.message_id)
+ {
+ mp.setMessageId(gen.generate());
+ }
+
+ if (opts.timestamp)
+ {
+ dp.setTimestamp(System.currentTimeMillis());
+ }
+
+ ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED,
+ new Header(dp, mp), body.slice());
+ count++;
+ }
+
+ ssn.messageCancel("echo-queue");
+
+ ssn.sync();
+ conn.close();
+ }
+
+ private static final void native_consumer(final Options opts) throws Exception
+ {
+ final DeliveryProperties dp = new DeliveryProperties();
+ final byte[] echo = new byte[0];
+ dp.setRoutingKey("echo-queue");
+ dp.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);
+ final MessageProperties mp = new MessageProperties();
+ final Object done = new Object();
+ org.apache.qpid.transport.Connection conn = getConnection
+ (opts,
+ new SessionDelegate() {
+
+ private long count = 0;
+ private long lastTime = 0;
+ private long start;
+
+ @Override public void messageTransfer
+ (org.apache.qpid.transport.Session ssn,
+ MessageTransfer mt)
+ {
+ if (count == 0)
+ {
+ start = System.currentTimeMillis();
+ }
+
+ boolean sample = opts.sample > 0 && (count % opts.sample) == 0;
+ long time = sample ? System.currentTimeMillis() : 0;
+
+ if (opts.window > 0 && (count % opts.window) == 0)
+ {
+ ssn.messageTransfer("amq.direct",
+ MessageAcceptMode.NONE,
+ MessageAcquireMode.PRE_ACQUIRED,
+ new Header(dp, mp),
+ echo);
+ }
+
+ if (sample)
+ {
+ sample(opts, Column.RIGHT, "NC", count, start, time, lastTime);
+ lastTime = time;
+ }
+ ssn.processed(mt);
+ count++;
+
+ if (opts.count > 0 && count >= opts.count)
+ {
+ synchronized (done)
+ {
+ done.notify();
+ }
+ }
+ }
+ });
+
+ Channel ch = conn.getChannel(0);
+ org.apache.qpid.transport.Session ssn = new org.apache.qpid.transport.Session("listener-session".getBytes());
+ ssn.attach(ch);
+ ssn.sessionAttach(ssn.getName());
+
+ ssn.invoke(new QueueDeclare().queue("test-queue").durable(false));
+ ssn.invoke(new QueueDeclare().queue("echo-queue").durable(false));
+ ssn.invoke(new ExchangeBind().exchange("amq.direct").queue("test-queue").bindingKey("test-queue"));
+ ssn.invoke(new ExchangeBind().exchange("amq.direct").queue("echo-queue").bindingKey("echo-queue"));
+
+ ssn.invoke(new MessageSubscribe()
+ .queue("test-queue")
+ .destination("test-queue")
+ .acceptMode(MessageAcceptMode.NONE)
+ .acquireMode(MessageAcquireMode.PRE_ACQUIRED));
+ ssn.messageSetFlowMode("test-queue", MessageFlowMode.WINDOW);
+ ssn.messageFlow("test-queue", MessageCreditUnit.MESSAGE, 0xFFFFFFFF);
+ ssn.messageFlow("test-queue", MessageCreditUnit.BYTE, 0xFFFFFFFF);
+
+ synchronized (done)
+ {
+ done.wait();
+ }
+
+ ssn.messageCancel("test-queue");
+
+ ssn.sync();
+ conn.close();
+ }
+
+}