From 24e93c0cf64e830980959c17777e86849cf5df7a Mon Sep 17 00:00:00 2001 From: Robert Godfrey Date: Sun, 14 Jul 2013 16:53:03 +0000 Subject: QPID-4659 : [Java Broker] preliminary refactoring in preparation for pluggable protocols git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1502993 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/qpid/server/AMQChannel.java | 1640 ------------------- .../qpid/server/ExtractResendAndRequeue.java | 134 -- .../qpid/server/ack/UnacknowledgedMessageMap.java | 69 - .../server/ack/UnacknowledgedMessageMapImpl.java | 183 --- .../qpid/server/flow/CreditCreditManager.java | 176 -- .../qpid/server/flow/FlowCreditManager_0_10.java | 28 - .../qpid/server/flow/WindowCreditManager.java | 206 --- .../qpid/server/handler/AccessRequestHandler.java | 85 - .../qpid/server/handler/BasicAckMethodHandler.java | 67 - .../server/handler/BasicCancelMethodHandler.java | 76 - .../server/handler/BasicConsumeMethodHandler.java | 177 -- .../qpid/server/handler/BasicGetMethodHandler.java | 175 -- .../server/handler/BasicPublishMethodHandler.java | 97 -- .../qpid/server/handler/BasicQosHandler.java | 58 - .../server/handler/BasicRecoverMethodHandler.java | 73 - .../handler/BasicRecoverSyncMethodHandler.java | 81 - .../server/handler/BasicRejectMethodHandler.java | 139 -- .../qpid/server/handler/ChannelCloseHandler.java | 76 - .../qpid/server/handler/ChannelCloseOkHandler.java | 53 - .../qpid/server/handler/ChannelFlowHandler.java | 68 - .../qpid/server/handler/ChannelOpenHandler.java | 142 -- .../handler/ConnectionCloseMethodHandler.java | 72 - .../handler/ConnectionCloseOkMethodHandler.java | 63 - .../handler/ConnectionOpenMethodHandler.java | 107 -- .../handler/ConnectionSecureOkMethodHandler.java | 132 -- .../handler/ConnectionStartOkMethodHandler.java | 154 -- .../handler/ConnectionTuneOkMethodHandler.java | 59 - .../qpid/server/handler/ExchangeBoundHandler.java | 192 --- .../server/handler/ExchangeDeclareHandler.java | 138 -- .../qpid/server/handler/ExchangeDeleteHandler.java | 95 -- .../server/handler/OnCurrentThreadExecutor.java | 34 - .../qpid/server/handler/QueueBindHandler.java | 160 -- .../qpid/server/handler/QueueDeclareHandler.java | 249 --- .../qpid/server/handler/QueueDeleteHandler.java | 128 -- .../qpid/server/handler/QueuePurgeHandler.java | 120 -- .../qpid/server/handler/QueueUnbindHandler.java | 138 -- .../server/handler/ServerMethodDispatcherImpl.java | 574 ------- .../handler/ServerMethodDispatcherImpl_0_9.java | 164 -- .../handler/ServerMethodDispatcherImpl_0_91.java | 168 -- .../handler/ServerMethodDispatcherImpl_8_0.java | 95 -- .../qpid/server/handler/TxCommitHandler.java | 85 - .../qpid/server/handler/TxRollbackHandler.java | 85 - .../qpid/server/handler/TxSelectHandler.java | 62 - .../server/handler/UnexpectedMethodException.java | 36 - .../server/logging/actors/AMQPChannelActor.java | 2 +- .../server/logging/subjects/ChannelLogSubject.java | 6 +- .../org/apache/qpid/server/message/AMQMessage.java | 249 --- .../qpid/server/message/AMQMessageReference.java | 41 - .../server/message/ContentHeaderBodyAdapter.java | 145 -- .../qpid/server/message/MessageMetaData.java | 347 ---- .../qpid/server/message/MessageMetaData_0_10.java | 277 ---- .../qpid/server/message/MessageTransferHeader.java | 170 -- .../server/message/MessageTransferMessage.java | 132 -- .../server/message/TransferMessageReference.java | 39 - .../server/output/HeaderPropertiesConverter.java | 149 -- .../server/output/ProtocolOutputConverter.java | 60 - .../server/output/ProtocolOutputConverterImpl.java | 452 ------ .../output/ProtocolOutputConverterRegistry.java | 90 -- .../protocol/AMQNoMethodHandlerException.java | 46 - .../qpid/server/protocol/AMQProtocolEngine.java | 1686 -------------------- .../qpid/server/protocol/AMQProtocolSession.java | 4 +- .../protocol/MultiVersionProtocolEngine.java | 9 +- .../qpid/server/protocol/ProtocolEngine_0_10.java | 198 --- .../qpid/server/protocol/ProtocolEngine_1_0_0.java | 427 ----- .../server/protocol/ProtocolEngine_1_0_0_SASL.java | 462 ------ .../server/protocol/v0_10/CreditCreditManager.java | 176 ++ .../ExplicitAcceptDispositionChangeListener.java | 93 ++ .../protocol/v0_10/FlowCreditManager_0_10.java | 30 + .../ImplicitAcceptDispositionChangeListener.java | 88 + .../v0_10/MessageAcceptCompletionListener.java | 56 + .../protocol/v0_10/MessageMetaData_0_10.java | 279 ++++ .../protocol/v0_10/MessageTransferHeader.java | 171 ++ .../protocol/v0_10/MessageTransferMessage.java | 136 ++ .../server/protocol/v0_10/ProtocolEngine_0_10.java | 198 +++ .../server/protocol/v0_10/ServerConnection.java | 551 +++++++ .../protocol/v0_10/ServerConnectionDelegate.java | 350 ++++ .../qpid/server/protocol/v0_10/ServerSession.java | 1000 ++++++++++++ .../protocol/v0_10/ServerSessionDelegate.java | 1583 ++++++++++++++++++ .../server/protocol/v0_10/Subscription_0_10.java | 1073 +++++++++++++ .../protocol/v0_10/TransferMessageReference.java | 41 + .../server/protocol/v0_10/WindowCreditManager.java | 207 +++ .../qpid/server/protocol/v0_8/AMQChannel.java | 1635 +++++++++++++++++++ .../qpid/server/protocol/v0_8/AMQMessage.java | 251 +++ .../server/protocol/v0_8/AMQMessageReference.java | 43 + .../protocol/v0_8/AMQNoMethodHandlerException.java | 46 + .../server/protocol/v0_8/AMQProtocolEngine.java | 1686 ++++++++++++++++++++ .../protocol/v0_8/ContentHeaderBodyAdapter.java | 146 ++ .../protocol/v0_8/ExtractResendAndRequeue.java | 133 ++ .../qpid/server/protocol/v0_8/MessageMetaData.java | 348 ++++ .../server/protocol/v0_8/SubscriptionFactory.java | 88 + .../protocol/v0_8/SubscriptionFactoryImpl.java | 138 ++ .../server/protocol/v0_8/SubscriptionImpl.java | 849 ++++++++++ .../protocol/v0_8/UnacknowledgedMessageMap.java | 69 + .../v0_8/UnacknowledgedMessageMapImpl.java | 183 +++ .../v0_8/handler/AccessRequestHandler.java | 85 + .../v0_8/handler/BasicAckMethodHandler.java | 67 + .../v0_8/handler/BasicCancelMethodHandler.java | 76 + .../v0_8/handler/BasicConsumeMethodHandler.java | 177 ++ .../v0_8/handler/BasicGetMethodHandler.java | 175 ++ .../v0_8/handler/BasicPublishMethodHandler.java | 97 ++ .../protocol/v0_8/handler/BasicQosHandler.java | 58 + .../v0_8/handler/BasicRecoverMethodHandler.java | 73 + .../handler/BasicRecoverSyncMethodHandler.java | 81 + .../v0_8/handler/BasicRejectMethodHandler.java | 139 ++ .../protocol/v0_8/handler/ChannelCloseHandler.java | 76 + .../v0_8/handler/ChannelCloseOkHandler.java | 53 + .../protocol/v0_8/handler/ChannelFlowHandler.java | 68 + .../protocol/v0_8/handler/ChannelOpenHandler.java | 142 ++ .../v0_8/handler/ConnectionCloseMethodHandler.java | 72 + .../handler/ConnectionCloseOkMethodHandler.java | 63 + .../v0_8/handler/ConnectionOpenMethodHandler.java | 107 ++ .../handler/ConnectionSecureOkMethodHandler.java | 132 ++ .../handler/ConnectionStartOkMethodHandler.java | 154 ++ .../handler/ConnectionTuneOkMethodHandler.java | 59 + .../v0_8/handler/ExchangeBoundHandler.java | 192 +++ .../v0_8/handler/ExchangeDeclareHandler.java | 138 ++ .../v0_8/handler/ExchangeDeleteHandler.java | 92 ++ .../v0_8/handler/OnCurrentThreadExecutor.java | 34 + .../protocol/v0_8/handler/QueueBindHandler.java | 159 ++ .../protocol/v0_8/handler/QueueDeclareHandler.java | 248 +++ .../protocol/v0_8/handler/QueueDeleteHandler.java | 128 ++ .../protocol/v0_8/handler/QueuePurgeHandler.java | 120 ++ .../protocol/v0_8/handler/QueueUnbindHandler.java | 137 ++ .../v0_8/handler/ServerMethodDispatcherImpl.java | 574 +++++++ .../handler/ServerMethodDispatcherImpl_0_9.java | 164 ++ .../handler/ServerMethodDispatcherImpl_0_91.java | 168 ++ .../handler/ServerMethodDispatcherImpl_8_0.java | 95 ++ .../protocol/v0_8/handler/TxCommitHandler.java | 85 + .../protocol/v0_8/handler/TxRollbackHandler.java | 85 + .../protocol/v0_8/handler/TxSelectHandler.java | 62 + .../v0_8/handler/UnexpectedMethodException.java | 36 + .../v0_8/output/HeaderPropertiesConverter.java | 149 ++ .../v0_8/output/ProtocolOutputConverter.java | 60 + .../v0_8/output/ProtocolOutputConverterImpl.java | 452 ++++++ .../output/ProtocolOutputConverterRegistry.java | 90 ++ .../qpid/server/protocol/v0_8/state/AMQState.java | 36 + .../protocol/v0_8/state/AMQStateManager.java | 162 ++ .../state/IllegalStateTransitionException.java | 52 + .../v0_8/state/StateAwareMethodListener.java | 34 + .../server/protocol/v0_8/state/StateListener.java | 30 + .../server/protocol/v1_0/ProtocolEngine_1_0_0.java | 427 +++++ .../protocol/v1_0/ProtocolEngine_1_0_0_SASL.java | 462 ++++++ .../server/protocol/v1_0/Subscription_1_0.java | 4 +- .../apache/qpid/server/queue/IncomingMessage.java | 2 +- .../org/apache/qpid/server/state/AMQState.java | 36 - .../apache/qpid/server/state/AMQStateManager.java | 162 -- .../state/IllegalStateTransitionException.java | 52 - .../server/state/StateAwareMethodListener.java | 34 - .../apache/qpid/server/state/StateListener.java | 30 - .../qpid/server/store/MessageMetaDataType.java | 4 +- .../ExplicitAcceptDispositionChangeListener.java | 94 -- .../ImplicitAcceptDispositionChangeListener.java | 89 -- .../MessageAcceptCompletionListener.java | 57 - .../server/subscription/SubscriptionFactory.java | 85 - .../subscription/SubscriptionFactoryImpl.java | 135 -- .../qpid/server/subscription/SubscriptionImpl.java | 849 ---------- .../server/subscription/Subscription_0_10.java | 1077 ------------- .../qpid/server/transport/ServerConnection.java | 551 ------- .../server/transport/ServerConnectionDelegate.java | 351 ---- .../qpid/server/transport/ServerSession.java | 1003 ------------ .../server/transport/ServerSessionDelegate.java | 1590 ------------------ .../VirtualHostConfigRecoveryHandler.java | 4 +- .../org/apache/qpid/server/AMQChannelTest.java | 143 -- .../qpid/server/ExtractResendAndRequeueTest.java | 256 --- .../apache/qpid/server/ack/AcknowledgeTest.java | 4 +- .../qpid/server/exchange/TopicExchangeTest.java | 4 +- .../qpid/server/flow/WindowCreditManagerTest.java | 83 - .../logging/actors/AMQPChannelActorTest.java | 2 +- .../server/logging/actors/CurrentActorTest.java | 2 +- .../logging/subjects/ChannelLogSubjectTest.java | 2 +- .../logging/subjects/ConnectionLogSubjectTest.java | 2 +- .../subjects/SubscriptionLogSubjectTest.java | 10 +- .../server/protocol/AMQProtocolEngineTest.java | 1 + .../protocol/InternalTestProtocolSession.java | 267 ---- .../qpid/server/protocol/MaxChannelsTest.java | 84 - .../server/protocol/v0_10/ServerSessionTest.java | 80 + .../protocol/v0_10/WindowCreditManagerTest.java | 84 + .../qpid/server/protocol/v0_8/AMQChannelTest.java | 142 ++ .../apache/qpid/server/protocol/v0_8/AckTest.java | 438 +++++ .../protocol/v0_8/ExtractResendAndRequeueTest.java | 257 +++ .../protocol/v0_8/InternalTestProtocolSession.java | 269 ++++ .../qpid/server/protocol/v0_8/MaxChannelsTest.java | 85 + .../qpid/server/queue/AMQPriorityQueueTest.java | 2 +- .../java/org/apache/qpid/server/queue/AckTest.java | 440 ----- .../qpid/server/queue/ConflationQueueListTest.java | 6 +- .../apache/qpid/server/queue/MockAMQMessage.java | 2 +- .../apache/qpid/server/queue/MockQueueEntry.java | 2 +- .../qpid/server/queue/MockStoredMessage.java | 2 +- .../qpid/server/queue/QueueEntryImplTestBase.java | 2 +- .../qpid/server/queue/SimpleAMQQueueTest.java | 5 +- .../server/queue/SimpleQueueEntryListTest.java | 25 +- .../server/queue/SortedQueueEntryListTest.java | 2 +- .../store/MessageStoreQuotaEventsTestBase.java | 2 +- .../qpid/server/store/ReferenceCountingTest.java | 4 +- .../subscription/QueueBrowserUsesNoAckTest.java | 7 +- .../subscription/SubscriptionFactoryImplTest.java | 13 +- .../qpid/server/transport/ServerSessionTest.java | 77 - .../apache/qpid/server/util/BrokerTestHelper.java | 4 +- 198 files changed, 19499 insertions(+), 19496 deletions(-) delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/HeaderPropertiesConverter.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.java create mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java create mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java delete mode 100755 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java delete mode 100644 qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java create mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java delete mode 100644 qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java (limited to 'qpid/java/broker/src') diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java deleted file mode 100644 index 4df40585d9..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ /dev/null @@ -1,1640 +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; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; - -import org.apache.log4j.Logger; -import org.apache.qpid.AMQConnectionException; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.Pre0_10CreditManager; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogMessage; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.AMQPChannelActor; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.ChannelMessages; -import org.apache.qpid.server.logging.messages.ExchangeMessages; -import org.apache.qpid.server.logging.subjects.ChannelLogSubject; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.InboundMessageAdapter; -import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.security.*; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.store.StoredMessage; -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.txn.AsyncAutoCommitTransaction; -import org.apache.qpid.server.txn.LocalTransaction; -import org.apache.qpid.server.txn.LocalTransaction.ActivityTimeAccessor; -import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.TransportException; - -public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.FutureRecorder -{ - public static final int DEFAULT_PREFETCH = 4096; - - private static final Logger _logger = Logger.getLogger(AMQChannel.class); - - //TODO use Broker property to configure message authorization requirements - private boolean _messageAuthorizationRequired = Boolean.getBoolean(BrokerProperties.PROPERTY_MSG_AUTH); - - private final int _channelId; - - - 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 - * value of this represents the last tag sent out - */ - private long _deliveryTag = 0; - - /** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */ - private AMQQueue _defaultQueue; - - /** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */ - private int _consumerTag; - - /** - * The current message - which may be partial in the sense that not all frames have been received yet - which has - * 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 IncomingMessage _currentMessage; - - /** Maps from consumer tag to subscription instance. Allows us to unsubscribe from a queue. */ - private final Map _tag2SubscriptionMap = new HashMap(); - - private final MessageStore _messageStore; - - private final LinkedList _unfinishedCommandsQueue = new LinkedList(); - - private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH); - - // Set of messages being acknowledged in the current transaction - private SortedSet _acknowledgedMessages = new TreeSet(); - - private final AtomicBoolean _suspended = new AtomicBoolean(false); - - private ServerTransaction _transaction; - - private final AtomicLong _txnStarts = new AtomicLong(0); - private final AtomicLong _txnCommits = new AtomicLong(0); - private final AtomicLong _txnRejects = new AtomicLong(0); - private final AtomicLong _txnCount = new AtomicLong(0); - - private final AMQProtocolSession _session; - private AtomicBoolean _closing = new AtomicBoolean(false); - - private final Set _blockingEntities = Collections.synchronizedSet(new HashSet()); - - private final AtomicBoolean _blocking = new AtomicBoolean(false); - - - private LogActor _actor; - private LogSubject _logSubject; - private volatile boolean _rollingBack; - - private static final Runnable NULL_TASK = new Runnable() { public void run() {} }; - private List _resendList = new ArrayList(); - private static final - AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); - private long _createTime = System.currentTimeMillis(); - - private final ClientDeliveryMethod _clientDeliveryMethod; - - private final TransactionTimeoutHelper _transactionTimeoutHelper; - private final UUID _id = UUID.randomUUID(); - - public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) - throws AMQException - { - _session = session; - _channelId = channelId; - - _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); - _logSubject = new ChannelLogSubject(this); - _actor.message(ChannelMessages.CREATE()); - - _messageStore = messageStore; - - // by default the session is non-transactional - _transaction = new AsyncAutoCommitTransaction(_messageStore, this); - - _clientDeliveryMethod = session.createDeliveryMethod(_channelId); - - _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() - { - @Override - public void doTimeoutAction(String reason) throws AMQException - { - closeConnection(reason); - } - }); - } - - /** Sets this channel to be part of a local transaction */ - public void setLocalTransactional() - { - _transaction = new LocalTransaction(_messageStore, new ActivityTimeAccessor() - { - @Override - public long getActivityTime() - { - return _session.getLastReceivedTime(); - } - }); - _txnStarts.incrementAndGet(); - } - - public boolean isTransactional() - { - return _transaction.isTransactional(); - } - - public void receivedComplete() - { - sync(); - } - - private void incrementOutstandingTxnsIfNecessary() - { - if(isTransactional()) - { - //There can currently only be at most one outstanding transaction - //due to only having LocalTransaction support. Set value to 1 if 0. - _txnCount.compareAndSet(0,1); - } - } - - private void decrementOutstandingTxnsIfNecessary() - { - if(isTransactional()) - { - //There can currently only be at most one outstanding transaction - //due to only having LocalTransaction support. Set value to 0 if 1. - _txnCount.compareAndSet(1,0); - } - } - - public Long getTxnCommits() - { - return _txnCommits.get(); - } - - public Long getTxnRejects() - { - return _txnRejects.get(); - } - - public Long getTxnCount() - { - return _txnCount.get(); - } - - public Long getTxnStart() - { - return _txnStarts.get(); - } - - public int getChannelId() - { - return _channelId; - } - - public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQSecurityException - { - String routingKey = info.getRoutingKey() == null ? null : info.getRoutingKey().asString(); - SecurityManager securityManager = getVirtualHost().getSecurityManager(); - if (!securityManager.authorisePublish(info.isImmediate(), routingKey, e.getName())) - { - throw new AMQSecurityException("Permission denied: " + e.getName()); - } - _currentMessage = new IncomingMessage(info, getProtocolSession().getReference()); - _currentMessage.setExchange(e); - } - - public void publishContentHeader(ContentHeaderBody contentHeaderBody) - throws AMQException - { - if (_currentMessage == null) - { - throw new AMQException("Received content header without previously receiving a BasicPublish frame"); - } - else - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Content header received on channel " + _channelId); - } - - _currentMessage.setContentHeaderBody(contentHeaderBody); - - _currentMessage.setExpiration(); - - _currentMessage.headersReceived(getProtocolSession().getLastReceivedTime()); - - _currentMessage.route(); - - deliverCurrentMessageIfComplete(); - } - } - - private void deliverCurrentMessageIfComplete() - throws AMQException - { - // check and deliver if header says body length is zero - if (_currentMessage.allContentReceived()) - { - try - { - final List destinationQueues = _currentMessage.getDestinationQueues(); - - if(!checkMessageUserId(_currentMessage.getContentHeader())) - { - _transaction.addPostTransactionAction(new WriteReturnAction(AMQConstant.ACCESS_REFUSED, "Access Refused", _currentMessage)); - } - else - { - if(destinationQueues == null || destinationQueues.isEmpty()) - { - handleUnroutableMessage(); - } - else - { - final StoredMessage handle = _messageStore.addMessage(_currentMessage.getMessageMetaData()); - _currentMessage.setStoredMessage(handle); - int bodyCount = _currentMessage.getBodyCount(); - if(bodyCount > 0) - { - long bodyLengthReceived = 0; - for(int i = 0 ; i < bodyCount ; i++) - { - ContentChunk contentChunk = _currentMessage.getContentChunk(i); - handle.addContent((int)bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData())); - bodyLengthReceived += contentChunk.getSize(); - } - } - - _transaction.addPostTransactionAction(new ServerTransaction.Action() - { - public void postCommit() - { - } - - public void onRollback() - { - handle.remove(); - } - }); - - _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues)); - incrementOutstandingTxnsIfNecessary(); - _currentMessage.getStoredMessage().flushToStore(); - } - } - } - finally - { - long bodySize = _currentMessage.getSize(); - long timestamp = ((BasicContentHeaderProperties) _currentMessage.getContentHeader().getProperties()).getTimestamp(); - _session.registerMessageReceived(bodySize, timestamp); - _currentMessage = null; - } - } - - } - - /** - * Either throws a {@link AMQConnectionException} or returns the message - * - * Pre-requisite: the current message is judged to have no destination queues. - * - * @throws AMQConnectionException if the message is mandatoryclose-on-no-route - * @see AMQProtocolSession#isCloseWhenNoRoute() - */ - private void handleUnroutableMessage() throws AMQConnectionException - { - boolean mandatory = _currentMessage.isMandatory(); - String description = currentMessageDescription(); - boolean closeOnNoRoute = _session.isCloseWhenNoRoute(); - - if(_logger.isDebugEnabled()) - { - _logger.debug(String.format( - "Unroutable message %s, mandatory=%s, transactionalSession=%s, closeOnNoRoute=%s", - description, mandatory, isTransactional(), closeOnNoRoute)); - } - - if (mandatory && isTransactional() && _session.isCloseWhenNoRoute()) - { - throw new AMQConnectionException( - AMQConstant.NO_ROUTE, - "No route for message " + currentMessageDescription(), - 0, 0, // default class and method ids - getProtocolSession().getProtocolVersion().getMajorVersion(), - getProtocolSession().getProtocolVersion().getMinorVersion(), - (Throwable) null); - } - - if (mandatory || _currentMessage.isImmediate()) - { - _transaction.addPostTransactionAction(new WriteReturnAction(AMQConstant.NO_ROUTE, "No Route for message " + currentMessageDescription(), _currentMessage)); - } - else - { - _actor.message(ExchangeMessages.DISCARDMSG(_currentMessage.getExchange().asString(), _currentMessage.getRoutingKey())); - } - } - - private String currentMessageDescription() - { - if(_currentMessage == null || !_currentMessage.allContentReceived()) - { - throw new IllegalStateException("Cannot create message description for message: " + _currentMessage); - } - - return String.format( - "[Exchange: %s, Routing key: %s]", - _currentMessage.getExchange(), - _currentMessage.getRoutingKey()); - } - - public void publishContentBody(ContentBody contentBody) throws AMQException - { - if (_currentMessage == null) - { - throw new AMQException("Received content body without previously receiving a JmsPublishBody"); - } - - if (_logger.isDebugEnabled()) - { - _logger.debug(debugIdentity() + " content body received on channel " + _channelId); - } - - try - { - final ContentChunk contentChunk = - _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(contentBody); - - _currentMessage.addContentBodyFrame(contentChunk); - - deliverCurrentMessageIfComplete(); - } - catch (AMQException e) - { - // we want to make sure we don't keep a reference to the message in the - // event of an error - _currentMessage = null; - throw e; - } - catch (RuntimeException e) - { - // we want to make sure we don't keep a reference to the message in the - // event of an error - _currentMessage = null; - throw e; - } - } - - public long getNextDeliveryTag() - { - return ++_deliveryTag; - } - - public int getNextConsumerTag() - { - return ++_consumerTag; - } - - - public Subscription getSubscription(AMQShortString subscription) - { - return _tag2SubscriptionMap.get(subscription); - } - - /** - * Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean - * up all subscriptions, even if the client does not explicitly unsubscribe from all queues. - * - * @param tag the tag chosen by the client (if null, server will generate one) - * @param queue the queue to subscribe to - * @param acks Are acks enabled for this subscriber - * @param filters Filters to apply to this subscriber - * - * @param noLocal Flag stopping own messages being received. - * @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 AMQException if something goes wrong - */ - public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks, - FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException - { - if (tag == null) - { - tag = new AMQShortString("sgen_" + getNextConsumerTag()); - } - - if (_tag2SubscriptionMap.containsKey(tag)) - { - throw new AMQException("Consumer already exists with same tag: " + tag); - } - - 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. - - _tag2SubscriptionMap.put(tag, subscription); - - try - { - queue.registerSubscription(subscription, exclusive); - } - catch (AMQException e) - { - _tag2SubscriptionMap.remove(tag); - throw e; - } - catch (RuntimeException e) - { - _tag2SubscriptionMap.remove(tag); - throw e; - } - return tag; - } - - /** - * Unsubscribe a consumer from a queue. - * @param consumerTag - * @return true if the consumerTag had a mapped queue that could be unregistered. - * @throws AMQException - */ - public boolean unsubscribeConsumer(AMQShortString consumerTag) throws AMQException - { - - Subscription sub = _tag2SubscriptionMap.remove(consumerTag); - if (sub != null) - { - try - { - sub.getSendLock(); - sub.getQueue().unregisterSubscription(sub); - } - finally - { - sub.releaseSendLock(); - } - return true; - } - else - { - _logger.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 - * - * @throws AMQException if there is an error during closure - */ - @Override - public void close() throws AMQException - { - close(null, null); - } - - public void close(AMQConstant cause, String message) throws AMQException - { - if(!_closing.compareAndSet(false, true)) - { - //Channel is already closing - return; - } - - LogMessage operationalLogMessage = cause == null ? - ChannelMessages.CLOSE() : - ChannelMessages.CLOSE_FORCED(cause.getCode(), message); - CurrentActor.get().message(_logSubject, operationalLogMessage); - - unsubscribeAllConsumers(); - _transaction.rollback(); - - try - { - requeue(); - } - catch (AMQException e) - { - _logger.error("Caught AMQException whilst attempting to requeue:" + e); - } - catch (TransportException e) - { - _logger.error("Caught TransportException whilst attempting to requeue:" + e); - } - } - - private void unsubscribeAllConsumers() throws AMQException - { - if (_logger.isInfoEnabled()) - { - if (!_tag2SubscriptionMap.isEmpty()) - { - _logger.info("Unsubscribing all consumers on channel " + toString()); - } - else - { - _logger.info("No consumers to unsubscribe on channel " + toString()); - } - } - - for (Map.Entry me : _tag2SubscriptionMap.entrySet()) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString()); - } - - Subscription sub = me.getValue(); - - try - { - sub.getSendLock(); - sub.getQueue().unregisterSubscription(sub); - } - finally - { - sub.releaseSendLock(); - } - - } - - _tag2SubscriptionMap.clear(); - } - - /** - * Add a message to the channel-based list of unacknowledged messages - * - * @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 subscription The consumer that is to acknowledge this message. - */ - public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription) - { - if (_logger.isDebugEnabled()) - { - if (entry.getQueue() == null) - { - _logger.debug("Adding unacked message with a null queue:" + entry); - } - else - { - if (_logger.isDebugEnabled()) - { - _logger.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag - + ") with a queue(" + entry.getQueue() + ") for " + subscription); - } - } - } - - _unacknowledgedMessageMap.add(deliveryTag, entry); - - } - - private final String id = "(" + System.identityHashCode(this) + ")"; - - public String debugIdentity() - { - return _channelId + id; - } - - /** - * Called to attempt re-delivery all outstanding unacknowledged messages on the channel. May result in delivery to - * this same channel or to other subscribers. - * - * @throws org.apache.qpid.AMQException if the requeue fails - */ - 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 messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages(); - - if (!messagesToBeDelivered.isEmpty()) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString()); - } - - } - - for (QueueEntry unacked : messagesToBeDelivered) - { - if (!unacked.isQueueDeleted()) - { - // Mark message redelivered - unacked.setRedelivered(); - - // Ensure message is released for redelivery - unacked.release(); - - } - else - { - unacked.discard(); - } - } - - } - - /** - * Requeue a single message - * - * @param deliveryTag The message to requeue - * - * @throws AMQException If something goes wrong. - */ - public void requeue(long deliveryTag) throws AMQException - { - QueueEntry unacked = _unacknowledgedMessageMap.remove(deliveryTag); - - if (unacked != null) - { - // Mark message redelivered - unacked.setRedelivered(); - - // Ensure message is released for redelivery - if (!unacked.isQueueDeleted()) - { - - // Ensure message is released for redelivery - unacked.release(); - - } - else - { - _logger.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked - + "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message."); - - unacked.discard(); - } - } - else - { - _logger.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists." - + _unacknowledgedMessageMap.size()); - - } - - } - - public boolean isMaxDeliveryCountEnabled(final long deliveryTag) - { - final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag); - if (queueEntry != null) - { - final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount(); - return maximumDeliveryCount > 0; - } - - return false; - } - - public boolean isDeliveredTooManyTimes(final long deliveryTag) - { - final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag); - if (queueEntry != null) - { - final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount(); - final int numDeliveries = queueEntry.getDeliveryCount(); - return maximumDeliveryCount != 0 && numDeliveries >= maximumDeliveryCount; - } - - return false; - } - - /** - * Called to resend all outstanding unacknowledged messages to this same channel. - * - * @param requeue Are the messages to be requeued or dropped. - * - * @throws AMQException When something goes wrong. - */ - public void resend(final boolean requeue) throws AMQException - { - - - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("unacked map Size:" + _unacknowledgedMessageMap.size()); - } - - // 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 ExtractResendAndRequeue(_unacknowledgedMessageMap, - msgToRequeue, - msgToResend, - requeue, - _messageStore)); - - - // Process Messages to Resend - if (_logger.isDebugEnabled()) - { - if (!msgToResend.isEmpty()) - { - _logger.debug("Preparing (" + msgToResend.size() + ") message to resend."); - } - else - { - _logger.debug("No message to resend."); - } - } - - for (Map.Entry entry : msgToResend.entrySet()) - { - QueueEntry message = entry.getValue(); - long deliveryTag = entry.getKey(); - - //Amend the delivery counter as the client hasn't seen these messages yet. - message.decrementDeliveryCount(); - - AMQQueue queue = message.getQueue(); - - // Without any details from the client about what has been processed we have to mark - // all messages in the unacked map as redelivered. - message.setRedelivered(); - - Subscription sub = message.getDeliveredSubscription(); - - if (sub != null) - { - - if(!queue.resend(message,sub)) - { - msgToRequeue.put(deliveryTag, message); - } - } - else - { - - if (_logger.isInfoEnabled()) - { - _logger.info("DeliveredSubscription not recorded so just requeueing(" + message.toString() - + ")to prevent loss"); - } - // move this message to requeue - msgToRequeue.put(deliveryTag, message); - } - } // for all messages - // } else !isSuspend - - if (_logger.isInfoEnabled()) - { - if (!msgToRequeue.isEmpty()) - { - _logger.info("Preparing (" + msgToRequeue.size() + ") message to requeue to."); - } - } - - // Process Messages to Requeue at the front of the queue - for (Map.Entry entry : msgToRequeue.entrySet()) - { - QueueEntry message = entry.getValue(); - long deliveryTag = entry.getKey(); - - //Amend the delivery counter as the client hasn't seen these messages yet. - message.decrementDeliveryCount(); - - _unacknowledgedMessageMap.remove(deliveryTag); - - message.setRedelivered(); - message.release(); - - } - } - - - /** - * Acknowledge one or more messages. - * - * @param deliveryTag the last delivery tag - * @param multiple if true will acknowledge all messages up to an including the delivery tag. if false only - * acknowledges the single message specified by the delivery tag - * - * @throws AMQException if the delivery tag is unknown (e.g. not outstanding) on this channel - */ - public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException - { - Collection ackedMessages = getAckedMessages(deliveryTag, multiple); - _transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages)); - } - - private Collection getAckedMessages(long deliveryTag, boolean multiple) - { - - return _unacknowledgedMessageMap.acknowledge(deliveryTag, multiple); - - } - - /** - * Used only for testing purposes. - * - * @return the map of unacknowledged messages - */ - public UnacknowledgedMessageMap getUnacknowledgedMessageMap() - { - return _unacknowledgedMessageMap; - } - - /** - * Called from the ChannelFlowHandler to suspend this Channel - * @param suspended boolean, should this Channel be suspended - */ - public void setSuspended(boolean suspended) - { - boolean wasSuspended = _suspended.getAndSet(suspended); - if (wasSuspended != suspended) - { - // Log Flow Started before we start the subscriptions - if (!suspended) - { - _actor.message(_logSubject, ChannelMessages.FLOW("Started")); - } - - - // This section takes two different approaches to perform to perform - // the same function. Ensuring that the Subscription has taken note - // of the change in Channel State - - // Here we have become unsuspended and so we ask each the queue to - // perform an Async delivery for each of the subscriptions in this - // Channel. The alternative would be to ensure that the subscription - // had received the change in suspension state. That way the logic - // behind decieding to start an async delivery was located with the - // Subscription. - if (wasSuspended) - { - // may need to deliver queued messages - for (Subscription s : _tag2SubscriptionMap.values()) - { - s.getQueue().deliverAsync(s); - } - } - - - // Here we have become suspended so we need to ensure that each of - // the Subscriptions has noticed this change so that we can be sure - // they are not still sending messages. Again the code here is a - // very simplistic approach to ensure that the change of suspension - // has been noticed by each of the Subscriptions. Unlike the above - // case we don't actually need to do anything else. - if (!wasSuspended) - { - // may need to deliver queued messages - for (Subscription s : _tag2SubscriptionMap.values()) - { - try - { - s.getSendLock(); - } - finally - { - s.releaseSendLock(); - } - } - } - - - // Log Suspension only after we have confirmed all suspensions are - // stopped. - if (suspended) - { - _actor.message(_logSubject, ChannelMessages.FLOW("Stopped")); - } - - } - } - - public boolean isSuspended() - { - return _suspended.get() || _closing.get() || _session.isClosing(); - } - - public void commit() throws AMQException - { - commit(null, false); - } - - - public void commit(final Runnable immediateAction, boolean async) throws AMQException - { - - if (!isTransactional()) - { - throw new AMQException("Fatal error: commit called on non-transactional channel"); - } - - if(async && _transaction instanceof LocalTransaction) - { - - ((LocalTransaction)_transaction).commitAsync(new Runnable() - { - @Override - public void run() - { - immediateAction.run(); - _txnCommits.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); - } - }); - } - else - { - _transaction.commit(immediateAction); - - _txnCommits.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); - } - } - - public void rollback() throws AMQException - { - rollback(NULL_TASK); - } - - public void rollback(Runnable postRollbackTask) throws AMQException - { - if (!isTransactional()) - { - throw new AMQException("Fatal error: commit called on non-transactional channel"); - } - - // stop all subscriptions - _rollingBack = true; - boolean requiresSuspend = _suspended.compareAndSet(false,true); - - // ensure all subscriptions have seen the change to the channel state - for(Subscription sub : _tag2SubscriptionMap.values()) - { - sub.getSendLock(); - sub.releaseSendLock(); - } - - try - { - _transaction.rollback(); - } - finally - { - _rollingBack = false; - - _txnRejects.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); - } - - postRollbackTask.run(); - - for(QueueEntry entry : _resendList) - { - Subscription sub = entry.getDeliveredSubscription(); - if(sub == null || sub.isClosed()) - { - entry.release(); - } - else - { - sub.getQueue().resend(entry, sub); - } - } - _resendList.clear(); - - if(requiresSuspend) - { - _suspended.set(false); - for(Subscription sub : _tag2SubscriptionMap.values()) - { - sub.getQueue().deliverAsync(sub); - } - - } - } - - public String toString() - { - return "["+_session.toString()+":"+_channelId+"]"; - } - - public void setDefaultQueue(AMQQueue queue) - { - _defaultQueue = queue; - } - - public AMQQueue getDefaultQueue() - { - return _defaultQueue; - } - - - public boolean isClosing() - { - return _closing.get(); - } - - public AMQProtocolSession getProtocolSession() - { - return _session; - } - - public FlowCreditManager getCreditManager() - { - return _creditManager; - } - - public void setCredit(final long prefetchSize, final int prefetchCount) - { - _actor.message(ChannelMessages.PREFETCH_SIZE(prefetchSize, prefetchCount)); - _creditManager.setCreditLimits(prefetchSize, prefetchCount); - } - - public MessageStore getMessageStore() - { - return _messageStore; - } - - 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; - } - - - private AMQMessage createAMQMessage(IncomingMessage incomingMessage) - throws AMQException - { - - AMQMessage message = new AMQMessage(incomingMessage.getStoredMessage()); - - message.setExpiration(incomingMessage.getExpiration()); - message.setConnectionIdentifier(_session.getReference()); - return message; - } - - private boolean checkMessageUserId(ContentHeaderBody header) - { - AMQShortString userID = - header.getProperties() instanceof BasicContentHeaderProperties - ? ((BasicContentHeaderProperties) header.getProperties()).getUserId() - : null; - - return (!_messageAuthorizationRequired || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString())); - - } - - @Override - public UUID getId() - { - return _id; - } - - public AMQConnectionModel getConnectionModel() - { - return _session; - } - - public String getClientID() - { - return String.valueOf(_session.getContextKey()); - } - - public LogSubject getLogSubject() - { - return _logSubject; - } - - @Override - public int compareTo(AMQSessionModel o) - { - return getId().compareTo(o.getId()); - } - - private class MessageDeliveryAction implements ServerTransaction.Action - { - private IncomingMessage _incommingMessage; - private List _destinationQueues; - - public MessageDeliveryAction(IncomingMessage currentMessage, - List destinationQueues) - { - _incommingMessage = currentMessage; - _destinationQueues = destinationQueues; - } - - public void postCommit() - { - try - { - final boolean immediate = _incommingMessage.isImmediate(); - - final AMQMessage amqMessage = createAMQMessage(_incommingMessage); - MessageReference ref = amqMessage.newReference(); - - for(int i = 0; i < _destinationQueues.size(); i++) - { - BaseQueue queue = _destinationQueues.get(i); - - BaseQueue.PostEnqueueAction action; - - if(immediate) - { - action = new ImmediateAction(queue); - } - else - { - action = null; - } - - queue.enqueue(amqMessage, isTransactional(), action); - - if(queue instanceof AMQQueue) - { - ((AMQQueue)queue).checkCapacity(AMQChannel.this); - } - - } - - _incommingMessage.getStoredMessage().flushToStore(); - ref.release(); - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - } - - public void onRollback() - { - // Maybe keep track of entries that were created and then delete them here in case of failure - // to in memory enqueue - } - - private class ImmediateAction implements BaseQueue.PostEnqueueAction - { - private final BaseQueue _queue; - - public ImmediateAction(BaseQueue queue) - { - _queue = queue; - } - - public void onEnqueue(QueueEntry entry) - { - if (!entry.getDeliveredToConsumer() && entry.acquire()) - { - - - ServerTransaction txn = new LocalTransaction(_messageStore); - Collection entries = new ArrayList(1); - entries.add(entry); - final AMQMessage message = (AMQMessage) entry.getMessage(); - txn.dequeue(_queue, entry.getMessage(), - new MessageAcknowledgeAction(entries) - { - @Override - public void postCommit() - { - try - { - final - ProtocolOutputConverter outputConverter = - _session.getProtocolOutputConverter(); - - outputConverter.writeReturn(message.getMessagePublishInfo(), - message.getContentHeaderBody(), - message, - _channelId, - AMQConstant.NO_CONSUMERS.getCode(), - IMMEDIATE_DELIVERY_REPLY_TEXT); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - super.postCommit(); - } - } - ); - txn.commit(); - - - } - - } - } - } - - private class MessageAcknowledgeAction implements ServerTransaction.Action - { - private final Collection _ackedMessages; - - public MessageAcknowledgeAction(Collection ackedMessages) - { - _ackedMessages = ackedMessages; - } - - public void postCommit() - { - try - { - for(QueueEntry entry : _ackedMessages) - { - entry.discard(); - } - } - finally - { - _acknowledgedMessages.clear(); - } - - } - - public void onRollback() - { - // explicit rollbacks resend the message after the rollback-ok is sent - if(_rollingBack) - { - _resendList.addAll(_ackedMessages); - } - else - { - try - { - for(QueueEntry entry : _ackedMessages) - { - entry.release(); - } - } - finally - { - _acknowledgedMessages.clear(); - } - } - - } - } - - private class WriteReturnAction implements ServerTransaction.Action - { - private final AMQConstant _errorCode; - private final IncomingMessage _message; - private final String _description; - - public WriteReturnAction(AMQConstant errorCode, - String description, - IncomingMessage message) - { - _errorCode = errorCode; - _message = message; - _description = description; - } - - public void postCommit() - { - try - { - _session.getProtocolOutputConverter().writeReturn(_message.getMessagePublishInfo(), - _message.getContentHeader(), - _message, - _channelId, - _errorCode.getCode(), - AMQShortString.valueOf(_description, true, true)); - } - catch (AMQException e) - { - //TODO - throw new RuntimeException(e); - } - - } - - public void onRollback() - { - } - } - - - public LogActor getLogActor() - { - return _actor; - } - - public synchronized void block() - { - if(_blockingEntities.add(this)) - { - if(_blocking.compareAndSet(false,true)) - { - _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED("** All Queues **")); - flow(false); - } - } - } - - public synchronized void unblock() - { - if(_blockingEntities.remove(this)) - { - if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false)) - { - _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); - - flow(true); - } - } - } - - public synchronized void block(AMQQueue queue) - { - if(_blockingEntities.add(queue)) - { - - if(_blocking.compareAndSet(false,true)) - { - _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getNameShortString().toString())); - flow(false); - } - } - } - - public synchronized void unblock(AMQQueue queue) - { - if(_blockingEntities.remove(queue)) - { - if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false) && !isClosing()) - { - _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); - - flow(true); - } - } - } - - public boolean onSameConnection(InboundMessage inbound) - { - if(inbound instanceof IncomingMessage) - { - IncomingMessage incoming = (IncomingMessage) inbound; - return getProtocolSession().getReference() == incoming.getConnectionReference(); - } - return false; - } - - public int getUnacknowledgedMessageCount() - { - return getUnacknowledgedMessageMap().size(); - } - - private void flow(boolean flow) - { - MethodRegistry methodRegistry = _session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createChannelFlowBody(flow); - _session.writeFrame(responseBody.generateFrame(_channelId)); - } - - @Override - public boolean getBlocking() - { - return _blocking.get(); - } - - public VirtualHost getVirtualHost() - { - return getProtocolSession().getVirtualHost(); - } - - public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException - { - _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); - } - - /** - * Typically called from the HouseKeepingThread instead of the main receiver thread, - * therefore uses a lock to close the connection in a thread-safe manner. - */ - private void closeConnection(String reason) throws AMQException - { - Lock receivedLock = _session.getReceivedLock(); - receivedLock.lock(); - try - { - _session.close(AMQConstant.RESOURCE_ERROR, reason); - } - finally - { - receivedLock.unlock(); - } - } - - public void deadLetter(long deliveryTag) throws AMQException - { - final UnacknowledgedMessageMap unackedMap = getUnacknowledgedMessageMap(); - final QueueEntry rejectedQueueEntry = unackedMap.get(deliveryTag); - - if (rejectedQueueEntry == null) - { - _logger.warn("No message found, unable to DLQ delivery tag: " + deliveryTag); - return; - } - else - { - final ServerMessage msg = rejectedQueueEntry.getMessage(); - - final AMQQueue queue = rejectedQueueEntry.getQueue(); - - final Exchange altExchange = queue.getAlternateExchange(); - unackedMap.remove(deliveryTag); - - if (altExchange == null) - { - _logger.debug("No alternate exchange configured for queue, must discard the message as unable to DLQ: delivery tag: " + deliveryTag); - _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), queue.getName(), msg.getRoutingKey())); - rejectedQueueEntry.discard(); - return; - } - - final InboundMessage m = new InboundMessageAdapter(rejectedQueueEntry); - - final List destinationQueues = altExchange.route(m); - - if (destinationQueues == null || destinationQueues.isEmpty()) - { - _logger.debug("Routing process provided no queues to enqueue the message on, must discard message as unable to DLQ: delivery tag: " + deliveryTag); - _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), altExchange.getName())); - rejectedQueueEntry.discard(); - return; - } - - rejectedQueueEntry.routeToAlternate(); - - //output operational logging for each delivery post commit - for (final BaseQueue destinationQueue : destinationQueues) - { - _actor.message(_logSubject, ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); - } - - } - } - - public void recordFuture(final StoreFuture future, final ServerTransaction.Action action) - { - _unfinishedCommandsQueue.add(new AsyncCommand(future, action)); - } - - public void sync() - { - if(_logger.isDebugEnabled()) - { - _logger.debug("sync() called on channel " + debugIdentity()); - } - - AsyncCommand cmd; - while((cmd = _unfinishedCommandsQueue.poll()) != null) - { - cmd.awaitReadyForCompletion(); - cmd.complete(); - } - if(_transaction instanceof LocalTransaction) - { - ((LocalTransaction)_transaction).sync(); - } - } - - private static class AsyncCommand - { - private final StoreFuture _future; - private ServerTransaction.Action _action; - - public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action) - { - _future = future; - _action = action; - } - - void awaitReadyForCompletion() - { - _future.waitForCompletion(); - } - - void complete() - { - if(!_future.isComplete()) - { - _future.waitForCompletion(); - } - _action.postCommit(); - _action = null; - } - } - - @Override - public int getConsumerCount() - { - return _tag2SubscriptionMap.size(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java deleted file mode 100644 index 0c0b1cf548..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.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.qpid.server; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.ServerTransaction; - -import java.util.Map; - -public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor -{ - private static final Logger _log = Logger.getLogger(ExtractResendAndRequeue.class); - - private final Map _msgToRequeue; - private final Map _msgToResend; - private final boolean _requeueIfUnabletoResend; - private final UnacknowledgedMessageMap _unacknowledgedMessageMap; - private final MessageStore _transactionLog; - - public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap, - Map msgToRequeue, - Map msgToResend, - boolean requeueIfUnabletoResend, - MessageStore txnLog) - { - _unacknowledgedMessageMap = unacknowledgedMessageMap; - _msgToRequeue = msgToRequeue; - _msgToResend = msgToResend; - _requeueIfUnabletoResend = requeueIfUnabletoResend; - _transactionLog = txnLog; - } - - public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException - { - - message.setRedelivered(); - final Subscription subscription = message.getDeliveredSubscription(); - if (subscription != null) - { - // Consumer exists - if (!subscription.isClosed()) - { - _msgToResend.put(deliveryTag, message); - } - else // consumer has gone - { - _msgToRequeue.put(deliveryTag, message); - } - } - else - { - // Message has no consumer tag, so was "delivered" to a GET - // or consumer no longer registered - // cannot resend, so re-queue. - if (!message.isQueueDeleted()) - { - if (_requeueIfUnabletoResend) - { - _msgToRequeue.put(deliveryTag, message); - } - else - { - - dequeueEntry(message); - _log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message); - } - } - else - { - dequeueEntry(message); - _log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message); - } - } - - // false means continue processing - return false; - } - - - private void dequeueEntry(final QueueEntry node) - { - ServerTransaction txn = new AutoCommitTransaction(_transactionLog); - dequeueEntry(node, txn); - } - - private void dequeueEntry(final QueueEntry node, ServerTransaction txn) - { - txn.dequeue(node.getQueue(), node.getMessage(), - new ServerTransaction.Action() - { - - public void postCommit() - { - node.discard(); - } - - public void onRollback() - { - - } - }); - } - - public void visitComplete() - { - _unacknowledgedMessageMap.clear(); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java deleted file mode 100644 index 842b36cf75..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java +++ /dev/null @@ -1,69 +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.server.queue.QueueEntry; - -import java.util.Collection; -import java.util.Set; - - -public interface UnacknowledgedMessageMap -{ - public interface Visitor - { - /** - * @param deliveryTag - *@param message the message being iterated over @return true to stop iteration, false to continue - * @throws AMQException - */ - boolean callback(final long deliveryTag, QueueEntry message) throws AMQException; - - void visitComplete(); - } - - void visit(Visitor visitor) throws AMQException; - - void add(long deliveryTag, QueueEntry message); - - QueueEntry remove(long deliveryTag); - - Collection cancelAllMessages(); - - int size(); - - void clear(); - - QueueEntry get(long deliveryTag); - - /** - * Get the set of delivery tags that are outstanding. - * - * @return a set of delivery tags - */ - Set getDeliveryTags(); - - Collection acknowledge(long deliveryTag, boolean multiple); - -} - - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java deleted file mode 100644 index b8b15c8c28..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java +++ /dev/null @@ -1,183 +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.server.queue.QueueEntry; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap -{ - private final Object _lock = new Object(); - - private long _unackedSize; - - private Map _map; - - private long _lastDeliveryTag; - - private final int _prefetchLimit; - - public UnacknowledgedMessageMapImpl(int prefetchLimit) - { - _prefetchLimit = prefetchLimit; - _map = new LinkedHashMap(prefetchLimit); - } - - public void collect(long deliveryTag, boolean multiple, Map msgs) - { - if (multiple) - { - collect(deliveryTag, msgs); - } - else - { - final QueueEntry entry = get(deliveryTag); - if(entry != null) - { - msgs.put(deliveryTag, entry); - } - } - - } - - public void remove(Map msgs) - { - synchronized (_lock) - { - for (Long deliveryTag : msgs.keySet()) - { - remove(deliveryTag); - } - } - } - - public QueueEntry remove(long deliveryTag) - { - synchronized (_lock) - { - - QueueEntry message = _map.remove(deliveryTag); - if(message != null) - { - _unackedSize -= message.getMessage().getSize(); - - } - - return message; - } - } - - public void visit(Visitor visitor) throws AMQException - { - synchronized (_lock) - { - Set> currentEntries = _map.entrySet(); - for (Map.Entry entry : currentEntries) - { - visitor.callback(entry.getKey().longValue(), entry.getValue()); - } - visitor.visitComplete(); - } - } - - public void add(long deliveryTag, QueueEntry message) - { - synchronized (_lock) - { - _map.put(deliveryTag, message); - _unackedSize += message.getMessage().getSize(); - _lastDeliveryTag = deliveryTag; - } - } - - public Collection cancelAllMessages() - { - synchronized (_lock) - { - Collection currentEntries = _map.values(); - _map = new LinkedHashMap(_prefetchLimit); - _unackedSize = 0l; - return currentEntries; - } - } - - public int size() - { - synchronized (_lock) - { - return _map.size(); - } - } - - public void clear() - { - synchronized (_lock) - { - _map.clear(); - _unackedSize = 0l; - } - } - - public QueueEntry get(long key) - { - synchronized (_lock) - { - return _map.get(key); - } - } - - public Set getDeliveryTags() - { - synchronized (_lock) - { - return _map.keySet(); - } - } - - public Collection acknowledge(long deliveryTag, boolean multiple) - { - Map ackedMessageMap = new LinkedHashMap(); - collect(deliveryTag, multiple, ackedMessageMap); - remove(ackedMessageMap); - return ackedMessageMap.values(); - } - - private void collect(long key, Map msgs) - { - synchronized (_lock) - { - for (Map.Entry entry : _map.entrySet()) - { - msgs.put(entry.getKey(),entry.getValue()); - if (entry.getKey() == key) - { - break; - } - } - } - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java deleted file mode 100644 index 09fe44338c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java +++ /dev/null @@ -1,176 +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.flow; - - -public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 -{ - private volatile long _bytesCredit; - private volatile long _messageCredit; - - public CreditCreditManager(long bytesCredit, long messageCredit) - { - _bytesCredit = bytesCredit; - _messageCredit = messageCredit; - setSuspended(!hasCredit()); - - } - - - public synchronized void setCreditLimits(final long bytesCredit, final long messageCredit) - { - _bytesCredit = bytesCredit; - _messageCredit = messageCredit; - - setSuspended(!hasCredit()); - - } - - - public long getMessageCredit() - { - return _messageCredit == -1L - ? Long.MAX_VALUE - : _messageCredit; - } - - public long getBytesCredit() - { - return _bytesCredit == -1L - ? Long.MAX_VALUE - : _bytesCredit; - } - - public synchronized void restoreCredit(final long messageCredit, final long bytesCredit) - { - } - - - public synchronized void addCredit(final long messageCredit, final long bytesCredit) - { - boolean notifyIncrease = true; - if(_messageCredit >= 0L && messageCredit > 0L) - { - notifyIncrease = _messageCredit != 0L; - _messageCredit += messageCredit; - } - - - - if(_bytesCredit >= 0L && bytesCredit > 0L) - { - notifyIncrease = notifyIncrease && bytesCredit>0; - _bytesCredit += bytesCredit; - - - - if(notifyIncrease) - { - notifyIncreaseBytesCredit(); - } - } - - - - setSuspended(!hasCredit()); - - } - - public void clearCredit() - { - _bytesCredit = 0l; - _messageCredit = 0l; - setSuspended(true); - } - - - public synchronized boolean hasCredit() - { - // Note !=, if credit is < 0 that indicates infinite credit - return (_bytesCredit != 0L && _messageCredit != 0L); - } - - public synchronized boolean useCreditForMessage(long msgSize) - { - if(_messageCredit >= 0L) - { - if(_messageCredit > 0) - { - if(_bytesCredit < 0L) - { - _messageCredit--; - - return true; - } - else if(msgSize <= _bytesCredit) - { - _messageCredit--; - _bytesCredit -= msgSize; - - return true; - } - else - { - return false; - } - } - else - { - setSuspended(true); - return false; - } - } - else if(_bytesCredit >= 0L) - { - if(msgSize <= _bytesCredit) - { - _bytesCredit -= msgSize; - - return true; - } - else - { - return false; - } - - } - else - { - return true; - } - - } - - public synchronized void stop() - { - if(_bytesCredit > 0) - { - _bytesCredit = 0; - } - if(_messageCredit > 0) - { - _messageCredit = 0; - } - - } - - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java deleted file mode 100755 index fea6eaf744..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java +++ /dev/null @@ -1,28 +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.flow; - -public interface FlowCreditManager_0_10 extends FlowCreditManager -{ - public void addCredit(long count, long bytes); - - void clearCredit(); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java deleted file mode 100644 index 2215c7bb3d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java +++ /dev/null @@ -1,206 +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.flow; - -import org.apache.log4j.Logger; - -public class WindowCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 -{ - private static final Logger LOGGER = Logger.getLogger(WindowCreditManager.class); - - private volatile long _bytesCreditLimit; - private volatile long _messageCreditLimit; - - private volatile long _bytesUsed; - private volatile long _messageUsed; - - public WindowCreditManager() - { - this(0L, 0L); - } - - public WindowCreditManager(long bytesCreditLimit, long messageCreditLimit) - { - _bytesCreditLimit = bytesCreditLimit; - _messageCreditLimit = messageCreditLimit; - setSuspended(!hasCredit()); - - } - - public long getBytesCreditLimit() - { - return _bytesCreditLimit; - } - - public long getMessageCreditLimit() - { - return _messageCreditLimit; - } - - public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit) - { - _bytesCreditLimit = bytesCreditLimit; - _messageCreditLimit = messageCreditLimit; - - setSuspended(!hasCredit()); - - } - - - public long getMessageCredit() - { - return _messageCreditLimit == -1L - ? Long.MAX_VALUE - : _messageUsed < _messageCreditLimit ? _messageCreditLimit - _messageUsed : 0L; - } - - public long getBytesCredit() - { - return _bytesCreditLimit == -1L - ? Long.MAX_VALUE - : _bytesUsed < _bytesCreditLimit ? _bytesCreditLimit - _bytesUsed : 0L; - } - - public synchronized void restoreCredit(final long messageCredit, final long bytesCredit) - { - _messageUsed -= messageCredit; - if(_messageUsed < 0L) - { - LOGGER.error("Message credit used value was negative: "+ _messageUsed); - _messageUsed = 0; - } - - boolean notifyIncrease = true; - - if(_messageCreditLimit > 0L) - { - notifyIncrease = (_messageUsed != _messageCreditLimit); - } - - _bytesUsed -= bytesCredit; - if(_bytesUsed < 0L) - { - LOGGER.error("Bytes credit used value was negative: "+ _messageUsed); - _bytesUsed = 0; - } - - if(_bytesCreditLimit > 0L) - { - notifyIncrease = notifyIncrease && bytesCredit>0; - - if(notifyIncrease) - { - notifyIncreaseBytesCredit(); - } - } - - setSuspended(!hasCredit()); - } - - - - public synchronized boolean hasCredit() - { - return (_bytesCreditLimit < 0L || _bytesCreditLimit > _bytesUsed) - && (_messageCreditLimit < 0L || _messageCreditLimit > _messageUsed); - } - - public synchronized boolean useCreditForMessage(final long msgSize) - { - if(_messageCreditLimit >= 0L) - { - if(_messageUsed < _messageCreditLimit) - { - if(_bytesCreditLimit < 0L) - { - _messageUsed++; - - return true; - } - else if(_bytesUsed + msgSize <= _bytesCreditLimit) - { - _messageUsed++; - _bytesUsed += msgSize; - - return true; - } - else - { - return false; - } - } - else - { - setSuspended(true); - return false; - } - } - else if(_bytesCreditLimit >= 0L) - { - if(_bytesUsed + msgSize <= _bytesCreditLimit) - { - _bytesUsed += msgSize; - - return true; - } - else - { - return false; - } - - } - else - { - return true; - } - - } - - - public synchronized void addCredit(long count, long bytes) - { - if(bytes > 0) - { - _bytesCreditLimit += bytes; - } - else if(bytes == -1) - { - _bytesCreditLimit = -1; - } - - - if(count > 0) - { - _messageCreditLimit += count; - } - else if(count == -1) - { - _messageCreditLimit = -1; - } - } - - public void clearCredit() - { - _bytesCreditLimit = 0l; - _messageCreditLimit = 0l; - setSuspended(true); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java deleted file mode 100644 index 84812485fd..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java +++ /dev/null @@ -1,85 +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.handler; - - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AccessRequestBody; -import org.apache.qpid.framing.AccessRequestOkBody; -import org.apache.qpid.framing.MethodRegistry; -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.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -/** - * @author Apache Software Foundation - * - * - */ -public class AccessRequestHandler implements StateAwareMethodListener -{ - 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(); - final AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - 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; - if(methodRegistry instanceof MethodRegistry_0_9) - { - response = ((MethodRegistry_0_9)methodRegistry).createAccessRequestOkBody(0); - } - else if(methodRegistry instanceof MethodRegistry_8_0) - { - response = ((MethodRegistry_8_0)methodRegistry).createAccessRequestOkBody(0); - } - else - { - throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9"); - } - - channel.sync(); - session.writeFrame(response.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java deleted file mode 100644 index 398a3ff58a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java +++ /dev/null @@ -1,67 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.BasicAckBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicAckMethodHandler implements StateAwareMethodListener -{ - private static final Logger _log = Logger.getLogger(BasicAckMethodHandler.class); - - private static final BasicAckMethodHandler _instance = new BasicAckMethodHandler(); - - public static BasicAckMethodHandler getInstance() - { - return _instance; - } - - private BasicAckMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, BasicAckBody body, int channelId) throws AMQException - { - AMQProtocolSession protocolSession = stateManager.getProtocolSession(); - - - if (_log.isDebugEnabled()) - { - _log.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId); - } - - final AMQChannel channel = protocolSession.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - // this method throws an AMQException if the delivery tag is not known - channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple()); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java deleted file mode 100644 index 0741385d42..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.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.qpid.server.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.BasicCancelBody; -import org.apache.qpid.framing.BasicCancelOkBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicCancelMethodHandler implements StateAwareMethodListener -{ - private static final Logger _log = Logger.getLogger(BasicCancelMethodHandler.class); - - private static final BasicCancelMethodHandler _instance = new BasicCancelMethodHandler(); - - public static BasicCancelMethodHandler getInstance() - { - return _instance; - } - - private BasicCancelMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, BasicCancelBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - final AMQChannel channel = session.getChannel(channelId); - - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - if (_log.isDebugEnabled()) - { - _log.debug("BasicCancel: for:" + body.getConsumerTag() + - " nowait:" + body.getNowait()); - } - - channel.unsubscribeConsumer(body.getConsumerTag()); - if (!body.getNowait()) - { - MethodRegistry methodRegistry = session.getMethodRegistry(); - BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag()); - channel.sync(); - session.writeFrame(cancelOkBody.generateFrame(channelId)); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java deleted file mode 100644 index 514829625d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicConsumeBody; -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.protocol.AMQSessionModel; -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; - -public class BasicConsumeMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(BasicConsumeMethodHandler.class); - - private static final BasicConsumeMethodHandler _instance = new BasicConsumeMethodHandler(); - - public static BasicConsumeMethodHandler getInstance() - { - return _instance; - } - - private BasicConsumeMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, BasicConsumeBody body, int channelId) throws AMQException - { - AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); - - AMQChannel channel = protocolConnection.getChannel(channelId); - VirtualHost vHost = protocolConnection.getVirtualHost(); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - else - { - channel.sync(); - if (_logger.isDebugEnabled()) - { - _logger.debug("BasicConsume: from '" + body.getQueue() + - "' for:" + body.getConsumerTag() + - " nowait:" + body.getNowait() + - " args:" + body.getArguments()); - } - - AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue().intern()); - - if (queue == null) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("No queue for '" + body.getQueue() + "'"); - } - if (body.getQueue() != null) - { - String msg = "No such queue, '" + body.getQueue() + "'"; - throw body.getChannelException(AMQConstant.NOT_FOUND, msg); - } - else - { - String msg = "No queue name provided, no default queue defined."; - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg); - } - } - else - { - final AMQShortString consumerTagName; - - if (queue.isExclusive() && !queue.isDurable()) - { - AMQSessionModel session = queue.getExclusiveOwningSession(); - if (session == null || session.getConnectionModel() != protocolConnection) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); - } - } - - if (body.getConsumerTag() != null) - { - consumerTagName = body.getConsumerTag().intern(); - } - else - { - consumerTagName = null; - } - - try - { - if(consumerTagName == null || channel.getSubscription(consumerTagName) == null) - { - - AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(), - body.getArguments(), body.getNoLocal(), body.getExclusive()); - if (!body.getNowait()) - { - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - } - } - else - { - AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'"); - - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode - msg, // replytext - body.getClazz(), - body.getMethod()); - protocolConnection.writeFrame(responseBody.generateFrame(0)); - } - - } - catch (org.apache.qpid.AMQInvalidArgumentException ise) - { - _logger.debug("Closing connection due to invalid selector"); - - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(), - new AMQShortString(ise.getMessage()), - body.getClazz(), - body.getMethod()); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - - } - catch (AMQQueue.ExistingExclusiveSubscription e) - { - throw body.getChannelException(AMQConstant.ACCESS_REFUSED, - "Cannot subscribe to queue " - + queue.getNameShortString() - + " as it already has an existing exclusive consumer"); - } - catch (AMQQueue.ExistingSubscriptionPreventsExclusive e) - { - throw body.getChannelException(AMQConstant.ACCESS_REFUSED, - "Cannot subscribe to queue " - + queue.getNameShortString() - + " exclusively as it already has a consumer"); - } - - } - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java deleted file mode 100644 index 191643493e..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java +++ /dev/null @@ -1,175 +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.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.flow.FlowCreditManager; -import org.apache.qpid.server.flow.MessageOnlyCreditManager; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -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.virtualhost.VirtualHost; - -public class BasicGetMethodHandler implements StateAwareMethodListener -{ - 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 protocolConnection = stateManager.getProtocolSession(); - - - VirtualHost vHost = protocolConnection.getVirtualHost(); - - AMQChannel channel = protocolConnection.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - else - { - channel.sync(); - 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 - { - if (queue.isExclusive()) - { - AMQSessionModel session = queue.getExclusiveOwningSession(); - if (session == null || session.getConnectionModel() != protocolConnection) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue is exclusive, but not created on this Connection."); - } - } - - if (!performGet(queue,protocolConnection, channel, !body.getNoAck())) - { - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - // TODO - set clusterId - BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null); - - - protocolConnection.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() - { - - public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) - throws AMQException - { - singleMessageCredit.useCreditForMessage(entry.getMessage().getSize()); - if(entry.getMessage() instanceof AMQMessage) - { - session.getProtocolOutputConverter().writeGetOk(entry, channel.getChannelId(), - deliveryTag, queue.getMessageCount()); - entry.incrementDeliveryCount(); - } - else - { - //TODO Convert AMQP 0-10 message - throw new AMQException(AMQConstant.NOT_IMPLEMENTED, "Not implemented conversion of 0-10 message", null); - } - - } - }; - 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 = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(channel, session, null, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod); - } - - queue.registerSubscription(sub,false); - queue.flushSubscription(sub); - queue.unregisterSubscription(sub); - return(!singleMessageCredit.hasCredit()); - - - } - - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java deleted file mode 100644 index 85fee94143..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java +++ /dev/null @@ -1,97 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicPublishBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class BasicPublishMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(BasicPublishMethodHandler.class); - - private static final BasicPublishMethodHandler _instance = new BasicPublishMethodHandler(); - - - public static BasicPublishMethodHandler getInstance() - { - return _instance; - } - - private BasicPublishMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, BasicPublishBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - if (_logger.isDebugEnabled()) - { - _logger.debug("Publish received on channel " + channelId); - } - - AMQShortString exchangeName = body.getExchange(); - // TODO: check the delivery tag field details - is it unique across the broker or per subscriber? - if (exchangeName == null) - { - exchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME; - } - - VirtualHost vHost = session.getVirtualHost(); - Exchange exch = vHost.getExchange(exchangeName.toString()); - // if the exchange does not exist we raise a channel exception - if (exch == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name"); - } - else - { - // The partially populated BasicDeliver frame plus the received route body - // is stored in the channel. Once the final body frame has been received - // it is routed to the exchange. - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - MessagePublishInfo info = session.getMethodRegistry().getProtocolVersionMethodConverter().convertToInfo(body); - info.setExchange(exchangeName); - channel.setPublishFrame(info, exch); - } - } - -} - - - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java deleted file mode 100644 index 87a3d1c210..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java +++ /dev/null @@ -1,58 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.BasicQosBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicQosHandler implements StateAwareMethodListener -{ - private static final BasicQosHandler _instance = new BasicQosHandler(); - - public static BasicQosHandler getInstance() - { - return _instance; - } - - public void methodReceived(AMQStateManager stateManager, BasicQosBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.sync(); - channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount()); - - - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java deleted file mode 100644 index 0c4c9cac47..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java +++ /dev/null @@ -1,73 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.BasicRecoverBody; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicRecoverMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(BasicRecoverMethodHandler.class); - - private static final BasicRecoverMethodHandler _instance = new BasicRecoverMethodHandler(); - - public static BasicRecoverMethodHandler getInstance() - { - return _instance; - } - - public void methodReceived(AMQStateManager stateManager, BasicRecoverBody 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.v8_0)) - { - MethodRegistry_8_0 methodRegistry = (MethodRegistry_8_0) session.getMethodRegistry(); - AMQMethodBody recoverOk = methodRegistry.createBasicRecoverOkBody(); - channel.sync(); - session.writeFrame(recoverOk.generateFrame(channelId)); - - } - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java deleted file mode 100644 index 43ee8da64f..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java +++ /dev/null @@ -1,81 +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.handler; - - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.BasicRecoverSyncBody; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; -import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener -{ - 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.sync(); - 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)); - - } - else if(session.getProtocolVersion().equals(ProtocolVersion.v0_91)) - { - MethodRegistry_0_91 methodRegistry = (MethodRegistry_0_91) session.getMethodRegistry(); - AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody(); - session.writeFrame(recoverOk.generateFrame(channelId)); - - } - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java deleted file mode 100644 index de76050898..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java +++ /dev/null @@ -1,139 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.BasicRejectBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class BasicRejectMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(BasicRejectMethodHandler.class); - - private static BasicRejectMethodHandler _instance = new BasicRejectMethodHandler(); - - public static BasicRejectMethodHandler getInstance() - { - return _instance; - } - - private BasicRejectMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, BasicRejectBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - if (_logger.isDebugEnabled()) - { - _logger.debug("Rejecting:" + body.getDeliveryTag() + - ": Requeue:" + body.getRequeue() + - " on channel:" + channel.debugIdentity()); - } - - long deliveryTag = body.getDeliveryTag(); - - QueueEntry message = channel.getUnacknowledgedMessageMap().get(deliveryTag); - - if (message == null) - { - _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag); - } - else - { - if (message.isQueueDeleted()) - { - _logger.warn("Message's Queue has already been purged, dropping message"); - message = channel.getUnacknowledgedMessageMap().remove(deliveryTag); - if(message != null) - { - message.discard(); - } - return; - } - - if (message.getMessage() == null) - { - _logger.warn("Message has already been purged, unable to Reject."); - return; - } - - - if (_logger.isDebugEnabled()) - { - _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() + - ": Requeue:" + body.getRequeue() + - " on channel:" + channel.debugIdentity()); - } - - message.reject(); - - if (body.getRequeue()) - { - channel.requeue(deliveryTag); - - //this requeue represents a message rejected from the pre-dispatch queue - //therefore we need to amend the delivery counter. - message.decrementDeliveryCount(); - } - else - { - final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag); - _logger.debug("maxDeliveryCountEnabled: " + maxDeliveryCountEnabled + " deliveryTag " + deliveryTag); - if (maxDeliveryCountEnabled) - { - final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag); - _logger.debug("deliveredTooManyTimes: " + deliveredTooManyTimes + " deliveryTag " + deliveryTag); - if (deliveredTooManyTimes) - { - channel.deadLetter(body.getDeliveryTag()); - } - else - { - //this requeue represents a message rejected because of a recover/rollback that we - //are not ready to DLQ. We rely on the reject command to resend from the unacked map - //and therefore need to increment the delivery counter so we cancel out the effect - //of the AMQChannel#resend() decrement. - message.incrementDeliveryCount(); - } - } - else - { - channel.deadLetter(body.getDeliveryTag()); - } - } - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java deleted file mode 100644 index 0c8ab318b2..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.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.qpid.server.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ChannelCloseBody; -import org.apache.qpid.framing.ChannelCloseOkBody; -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.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ChannelCloseHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ChannelCloseHandler.class); - - private static ChannelCloseHandler _instance = new ChannelCloseHandler(); - - public static ChannelCloseHandler getInstance() - { - return _instance; - } - - private ChannelCloseHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ChannelCloseBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - if (_logger.isInfoEnabled()) - { - _logger.info("Received channel close for id " + channelId + " citing class " + body.getClassId() + - " and method " + body.getMethodId()); - } - - - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getConnectionException(AMQConstant.CHANNEL_ERROR, "Trying to close unknown channel"); - } - channel.sync(); - session.closeChannel(channelId); - // Client requested closure so we don't wait for ok we send it - stateManager.getProtocolSession().closeChannelOk(channelId); - - MethodRegistry methodRegistry = session.getMethodRegistry(); - ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java deleted file mode 100644 index 54b3f813af..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java +++ /dev/null @@ -1,53 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ChannelCloseOkHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ChannelCloseOkHandler.class); - - private static ChannelCloseOkHandler _instance = new ChannelCloseOkHandler(); - - public static ChannelCloseOkHandler getInstance() - { - return _instance; - } - - private ChannelCloseOkHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ChannelCloseOkBody body, int channelId) throws AMQException - { - - _logger.info("Received channel-close-ok for channel-id " + channelId); - - // Let the Protocol Session know the channel is now closed. - stateManager.getProtocolSession().closeChannelOk(channelId); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java deleted file mode 100644 index a736ad5fb0..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java +++ /dev/null @@ -1,68 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.ChannelFlowBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ChannelFlowHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ChannelFlowHandler.class); - - private static ChannelFlowHandler _instance = new ChannelFlowHandler(); - - public static ChannelFlowHandler getInstance() - { - return _instance; - } - - private ChannelFlowHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ChannelFlowBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.sync(); - channel.setSuspended(!body.getActive()); - _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive()); - - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive()); - session.writeFrame(responseBody.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java deleted file mode 100644 index 81734d7825..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java +++ /dev/null @@ -1,142 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ChannelOpenBody; -import org.apache.qpid.framing.ChannelOpenOkBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; -import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; -import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.UUID; - -public class ChannelOpenHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ChannelOpenHandler.class); - - private static ChannelOpenHandler _instance = new ChannelOpenHandler(); - - public static ChannelOpenHandler getInstance() - { - return _instance; - } - - private ChannelOpenHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ChannelOpenBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); - - // Protect the broker against out of order frame request. - if (virtualHost == null) - { - throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null); - } - _logger.info("Connecting to: " + virtualHost.getName()); - - final AMQChannel channel = new AMQChannel(session,channelId, virtualHost.getMessageStore()); - - session.addChannel(channel); - - ChannelOpenOkBody response; - - ProtocolVersion pv = session.getProtocolVersion(); - - if(pv.equals(ProtocolVersion.v8_0)) - { - MethodRegistry_8_0 methodRegistry = (MethodRegistry_8_0) MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0); - response = methodRegistry.createChannelOpenOkBody(); - - } - else if(pv.equals(ProtocolVersion.v0_9)) - { - MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); - UUID uuid = UUID.randomUUID(); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - DataOutputStream dataOut = new DataOutputStream(output); - try - { - dataOut.writeLong(uuid.getMostSignificantBits()); - dataOut.writeLong(uuid.getLeastSignificantBits()); - dataOut.flush(); - dataOut.close(); - } - catch (IOException e) - { - // This *really* shouldn't happen as we're not doing any I/O - throw new RuntimeException("I/O exception when writing to byte array", e); - } - - // should really associate this channelId to the session - byte[] channelName = output.toByteArray(); - - response = methodRegistry.createChannelOpenOkBody(channelName); - } - else if(pv.equals(ProtocolVersion.v0_91)) - { - MethodRegistry_0_91 methodRegistry = (MethodRegistry_0_91) MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91); - UUID uuid = UUID.randomUUID(); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - DataOutputStream dataOut = new DataOutputStream(output); - try - { - dataOut.writeLong(uuid.getMostSignificantBits()); - dataOut.writeLong(uuid.getLeastSignificantBits()); - dataOut.flush(); - dataOut.close(); - } - catch (IOException e) - { - // This *really* shouldn't happen as we're not doing any I/O - throw new RuntimeException("I/O exception when writing to byte array", e); - } - - // should really associate this channelId to the session - byte[] channelName = output.toByteArray(); - - response = methodRegistry.createChannelOpenOkBody(channelName); - } - else - { - throw new AMQException(AMQConstant.INTERNAL_ERROR, "Got channel open for protocol version not catered for: " + pv, null); - } - - - session.writeFrame(response.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java deleted file mode 100644 index 7f0c0d2974..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java +++ /dev/null @@ -1,72 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.ConnectionCloseOkBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ConnectionCloseMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionCloseMethodHandler.class); - - private static ConnectionCloseMethodHandler _instance = new ConnectionCloseMethodHandler(); - - public static ConnectionCloseMethodHandler getInstance() - { - return _instance; - } - - private ConnectionCloseMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ConnectionCloseBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - if (_logger.isInfoEnabled()) - { - _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" + - body.getReplyText() + " for " + session); - } - try - { - session.closeSession(); - } - catch (Exception e) - { - _logger.error("Error closing protocol session: " + e, e); - } - - MethodRegistry methodRegistry = session.getMethodRegistry(); - ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); - - session.closeProtocolSession(); - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java deleted file mode 100644 index bd86c2d3f1..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java +++ /dev/null @@ -1,63 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ConnectionCloseOkBody; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ConnectionCloseOkMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionCloseOkMethodHandler.class); - - private static ConnectionCloseOkMethodHandler _instance = new ConnectionCloseOkMethodHandler(); - - public static ConnectionCloseOkMethodHandler getInstance() - { - return _instance; - } - - private ConnectionCloseOkMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ConnectionCloseOkBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - //todo should this not do more than just log the method? - _logger.info("Received Connection-close-ok"); - - try - { - stateManager.changeState(AMQState.CONNECTION_CLOSED); - session.closeSession(); - } - catch (Exception e) - { - _logger.error("Error closing protocol session: " + e, e); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java deleted file mode 100644 index eab28ac9d4..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java +++ /dev/null @@ -1,107 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ConnectionOpenBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.State; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class ConnectionOpenMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionOpenMethodHandler.class); - - private static ConnectionOpenMethodHandler _instance = new ConnectionOpenMethodHandler(); - - public static ConnectionOpenMethodHandler getInstance() - { - return _instance; - } - - private ConnectionOpenMethodHandler() - { - } - - private static AMQShortString generateClientID() - { - return new AMQShortString(Long.toString(System.currentTimeMillis())); - } - - public void methodReceived(AMQStateManager stateManager, ConnectionOpenBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - //ignore leading '/' - String virtualHostName; - if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/') - { - virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString(); - } - else - { - virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost()); - } - - VirtualHost virtualHost = stateManager.getVirtualHostRegistry().getVirtualHost(virtualHostName); - - if (virtualHost == null) - { - throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'"); - } - else - { - // Check virtualhost access - if (!virtualHost.getSecurityManager().accessVirtualhost(virtualHostName, session.getRemoteAddress())) - { - throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied: '" + virtualHost.getName() + "'"); - } - else if (virtualHost.getState() != State.ACTIVE) - { - throw body.getConnectionException(AMQConstant.CONNECTION_FORCED, "Virtual host '" + virtualHost.getName() + "' is not active"); - } - - session.setVirtualHost(virtualHost); - - // See Spec (0.8.2). Section 3.1.2 Virtual Hosts - if (session.getContextKey() == null) - { - session.setContextKey(generateClientID()); - } - - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost()); - - stateManager.changeState(AMQState.CONNECTION_OPEN); - - session.writeFrame(responseBody.generateFrame(channelId)); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java deleted file mode 100644 index 8927cfa94d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java +++ /dev/null @@ -1,132 +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.handler; - - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.ConnectionSecureBody; -import org.apache.qpid.framing.ConnectionSecureOkBody; -import org.apache.qpid.framing.ConnectionTuneBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - -public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionSecureOkMethodHandler.class); - - private static ConnectionSecureOkMethodHandler _instance = new ConnectionSecureOkMethodHandler(); - - public static ConnectionSecureOkMethodHandler getInstance() - { - return _instance; - } - - private ConnectionSecureOkMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ConnectionSecureOkBody body, int channelId) throws AMQException - { - Broker broker = stateManager.getBroker(); - AMQProtocolSession session = stateManager.getProtocolSession(); - - SubjectCreator subjectCreator = stateManager.getSubjectCreator(); - - SaslServer ss = session.getSaslServer(); - if (ss == null) - { - throw new AMQException("No SASL context set up in session"); - } - MethodRegistry methodRegistry = session.getMethodRegistry(); - SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); - switch (authResult.getStatus()) - { - case ERROR: - 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(), - AMQConstant.NOT_ALLOWED.getName(), - body.getClazz(), - body.getMethod()); - - session.writeFrame(connectionCloseBody.generateFrame(0)); - disposeSaslServer(session); - break; - case SUCCESS: - if (_logger.isInfoEnabled()) - { - _logger.info("Connected as: " + authResult.getSubject()); - } - stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); - - ConnectionTuneBody tuneBody = - methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT), - BrokerProperties.FRAME_SIZE, - (Integer)broker.getAttribute(Broker.CONNECTION_HEART_BEAT_DELAY)); - session.writeFrame(tuneBody.generateFrame(0)); - session.setAuthorizedSubject(authResult.getSubject()); - disposeSaslServer(session); - break; - case CONTINUE: - stateManager.changeState(AMQState.CONNECTION_NOT_AUTH); - - ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge()); - session.writeFrame(secureBody.generateFrame(0)); - } - } - - private void disposeSaslServer(AMQProtocolSession ps) - { - SaslServer ss = ps.getSaslServer(); - if (ss != null) - { - ps.setSaslServer(null); - try - { - ss.dispose(); - } - catch (SaslException e) - { - _logger.error("Error disposing of Sasl server: " + e); - } - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java deleted file mode 100644 index 5bfa080848..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java +++ /dev/null @@ -1,154 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.ConnectionSecureBody; -import org.apache.qpid.framing.ConnectionStartOkBody; -import org.apache.qpid.framing.ConnectionTuneBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - - -public class ConnectionStartOkMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionStartOkMethodHandler.class); - - private static ConnectionStartOkMethodHandler _instance = new ConnectionStartOkMethodHandler(); - - public static ConnectionStartOkMethodHandler getInstance() - { - return _instance; - } - - private ConnectionStartOkMethodHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException - { - Broker broker = stateManager.getBroker(); - AMQProtocolSession session = stateManager.getProtocolSession(); - - _logger.info("SASL Mechanism selected: " + body.getMechanism()); - _logger.info("Locale selected: " + body.getLocale()); - - SubjectCreator subjectCreator = stateManager.getSubjectCreator(); - SaslServer ss = null; - try - { - ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal()); - - if (ss == null) - { - throw body.getConnectionException(AMQConstant.RESOURCE_ERROR, "Unable to create SASL Server:" + body.getMechanism()); - } - - session.setSaslServer(ss); - - final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); - //save clientProperties - session.setClientProperties(body.getClientProperties()); - - MethodRegistry methodRegistry = session.getMethodRegistry(); - - switch (authResult.getStatus()) - { - case ERROR: - Exception cause = authResult.getCause(); - - _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage())); - - stateManager.changeState(AMQState.CONNECTION_CLOSING); - - ConnectionCloseBody closeBody = - methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode - AMQConstant.NOT_ALLOWED.getName(), - body.getClazz(), - body.getMethod()); - - session.writeFrame(closeBody.generateFrame(0)); - disposeSaslServer(session); - break; - - case SUCCESS: - if (_logger.isInfoEnabled()) - { - _logger.info("Connected as: " + authResult.getSubject()); - } - session.setAuthorizedSubject(authResult.getSubject()); - - stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); - - ConnectionTuneBody tuneBody = methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT), - BrokerProperties.FRAME_SIZE, - (Integer)broker.getAttribute(Broker.CONNECTION_HEART_BEAT_DELAY)); - session.writeFrame(tuneBody.generateFrame(0)); - break; - case CONTINUE: - stateManager.changeState(AMQState.CONNECTION_NOT_AUTH); - - ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge()); - session.writeFrame(secureBody.generateFrame(0)); - } - } - catch (SaslException e) - { - disposeSaslServer(session); - throw new AMQException("SASL error: " + e, e); - } - } - - private void disposeSaslServer(AMQProtocolSession ps) - { - SaslServer ss = ps.getSaslServer(); - if (ss != null) - { - ps.setSaslServer(null); - try - { - ss.dispose(); - } - catch (SaslException e) - { - _logger.error("Error disposing of Sasl server: " + e); - } - } - } - -} - - - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java deleted file mode 100644 index 299aad0fe7..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java +++ /dev/null @@ -1,59 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.ConnectionTuneOkBody; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ConnectionTuneOkMethodHandler.class); - - private static ConnectionTuneOkMethodHandler _instance = new ConnectionTuneOkMethodHandler(); - - public static ConnectionTuneOkMethodHandler getInstance() - { - return _instance; - } - - public void methodReceived(AMQStateManager stateManager, ConnectionTuneOkBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - if (_logger.isDebugEnabled()) - { - _logger.debug(body); - } - stateManager.changeState(AMQState.CONNECTION_NOT_OPENED); - session.initHeartbeats(body.getHeartbeat()); - session.setMaxFrameSize(body.getFrameMax()); - - long maxChannelNumber = body.getChannelMax(); - //0 means no implied limit, except that forced by protocol limitations (0xFFFF) - session.setMaximumNumberOfChannels( maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java deleted file mode 100644 index 8493e97215..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java +++ /dev/null @@ -1,192 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ExchangeBoundBody; -import org.apache.qpid.framing.ExchangeBoundOkBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -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.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.VirtualHost; - -/** - * @author Apache Software Foundation - * - * - */ -public class ExchangeBoundHandler implements StateAwareMethodListener -{ - private static final ExchangeBoundHandler _instance = new ExchangeBoundHandler(); - - public static final int OK = 0; - - public static final int EXCHANGE_NOT_FOUND = 1; - - public static final int QUEUE_NOT_FOUND = 2; - - public static final int NO_BINDINGS = 3; - - public static final int QUEUE_NOT_BOUND = 4; - - public static final int NO_QUEUE_BOUND_WITH_RK = 5; - - public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6; - - public static ExchangeBoundHandler getInstance() - { - return _instance; - } - - private ExchangeBoundHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ExchangeBoundBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - MethodRegistry methodRegistry = session.getMethodRegistry(); - - final AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.sync(); - - - AMQShortString exchangeName = body.getExchange(); - AMQShortString queueName = body.getQueue(); - AMQShortString routingKey = body.getRoutingKey(); - if (exchangeName == null) - { - throw new AMQException("Exchange exchange must not be null"); - } - Exchange exchange = virtualHost.getExchange(exchangeName.toString()); - ExchangeBoundOkBody response; - if (exchange == null) - { - - - response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND, - new AMQShortString("Exchange " + exchangeName + " not found")); - } - else if (routingKey == null) - { - if (queueName == null) - { - if (exchange.hasBindings()) - { - response = methodRegistry.createExchangeBoundOkBody(OK, null); - } - else - { - - response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS, // replyCode - null); // replyText - } - } - else - { - - AMQQueue queue = queueRegistry.getQueue(queueName); - if (queue == null) - { - - response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode - new AMQShortString("Queue " + queueName + " not found")); // replyText - } - else - { - if (exchange.isBound(queue)) - { - - response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode - null); // replyText - } - else - { - - response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND, // replyCode - new AMQShortString("Queue " + queueName + " not bound to exchange " + exchangeName)); // replyText - } - } - } - } - else if (queueName != null) - { - AMQQueue queue = queueRegistry.getQueue(queueName); - if (queue == null) - { - - response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode - new AMQShortString("Queue " + queueName + " not found")); // replyText - } - else - { - if (exchange.isBound(body.getRoutingKey(), queue)) - { - - response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode - null); // replyText - } - else - { - - String message = "Queue " + queueName + " not bound with routing key " + - body.getRoutingKey() + " to exchange " + exchangeName; - - if(message.length()>255) - { - message = message.substring(0,254); - } - response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, // replyCode - new AMQShortString(message)); // replyText - } - } - } - else - { - if (exchange.isBound(body.getRoutingKey())) - { - - response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode - null); // replyText - } - else - { - - response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK, // replyCode - new AMQShortString("No queue bound with routing key " + body.getRoutingKey() + - " to exchange " + exchangeName)); // replyText - } - } - session.writeFrame(response.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java deleted file mode 100644 index 437869ab01..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java +++ /dev/null @@ -1,138 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQConnectionException; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQUnknownExchangeType; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ExchangeDeclareBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.ExchangeExistsException; -import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class ExchangeDeclareHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(ExchangeDeclareHandler.class); - - private static final ExchangeDeclareHandler _instance = new ExchangeDeclareHandler(); - - public static ExchangeDeclareHandler getInstance() - { - return _instance; - } - - private ExchangeDeclareHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ExchangeDeclareBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); - final AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - final AMQShortString exchangeName = body.getExchange(); - if (_logger.isDebugEnabled()) - { - _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName); - } - - Exchange exchange; - - if (body.getPassive()) - { - exchange = virtualHost.getExchange(exchangeName == null ? null : exchangeName.toString()); - if(exchange == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName); - } - else if (!exchange.getTypeShortString().equals(body.getType()) && !(body.getType() == null || body.getType().length() ==0)) - { - - throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + - exchangeName + " of type " + exchange.getTypeShortString() - + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null); - } - - } - else - { - try - { - exchange = virtualHost.createExchange(null, - exchangeName == null ? null : exchangeName.intern().toString(), - body.getType() == null ? null : body.getType().intern().toString(), - body.getDurable(), - body.getAutoDelete(), - null); - - } - catch(ReservedExchangeNameException e) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Attempt to declare exchange: " + exchangeName + - " which begins with reserved prefix."); - - } - catch(ExchangeExistsException e) - { - exchange = e.getExistingExchange(); - if(!exchange.getTypeShortString().equals(body.getType())) - { - throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " - + exchangeName + " of type " - + exchange.getTypeShortString() - + " to " + body.getType() +".", - body.getClazz(), body.getMethod(), - body.getMajor(), body.getMinor(),null); - } - } - catch(AMQUnknownExchangeType e) - { - throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + exchangeName,e); - } - } - - - if(!body.getNowait()) - { - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody(); - channel.sync(); - session.writeFrame(responseBody.generateFrame(channelId)); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java deleted file mode 100644 index 25d0182202..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java +++ /dev/null @@ -1,95 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ExchangeDeleteBody; -import org.apache.qpid.framing.ExchangeDeleteOkBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeInUseException; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; -import org.apache.qpid.server.virtualhost.RequiredExchangeException; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.ExecutionErrorCode; - -public class ExchangeDeleteHandler implements StateAwareMethodListener -{ - private static final ExchangeDeleteHandler _instance = new ExchangeDeleteHandler(); - - public static ExchangeDeleteHandler getInstance() - { - return _instance; - } - - private ExchangeDeleteHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, ExchangeDeleteBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); - final AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.sync(); - try - { - final String exchangeName = body.getExchange() == null ? null : body.getExchange().toString(); - - final Exchange exchange = virtualHost.getExchange(exchangeName); - if(exchange == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange()); - } - - virtualHost.removeExchange(exchange, !body.getIfUnused()); - - ExchangeDeleteOkBody responseBody = session.getMethodRegistry().createExchangeDeleteOkBody(); - - session.writeFrame(responseBody.generateFrame(channelId)); - } - catch (ExchangeInUseException e) - { - throw body.getChannelException(AMQConstant.IN_USE, "Exchange in use"); - // TODO: sort out consistent channel close mechanism that does all clean up etc. - } - - catch (ExchangeIsAlternateException e) - { - throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange"); - - } - catch (RequiredExchangeException e) - { - throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange '"+body.getExchange()+"' cannot be deleted"); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.java deleted file mode 100644 index ac516b6133..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.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.handler; - -import java.util.concurrent.Executor; - -/** - * An executor that executes the task on the current thread. - */ -public class OnCurrentThreadExecutor implements Executor -{ - public void execute(Runnable command) - { - command.run(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java deleted file mode 100644 index 63b8bf3136..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java +++ /dev/null @@ -1,160 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.QueueBindBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -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 java.util.Map; - -public class QueueBindHandler implements StateAwareMethodListener -{ - private static final Logger _log = Logger.getLogger(QueueBindHandler.class); - - private static final QueueBindHandler _instance = new QueueBindHandler(); - - public static QueueBindHandler getInstance() - { - return _instance; - } - - private QueueBindHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, QueueBindBody body, int channelId) throws AMQException - { - AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); - VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - final AMQQueue queue; - final AMQShortString routingKey; - - if (body.getQueue() == null) - { - - queue = channel.getDefaultQueue(); - - if (queue == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "No default queue defined on channel and queue was null"); - } - - if (body.getRoutingKey() == null) - { - routingKey = queue.getNameShortString(); - } - else - { - routingKey = body.getRoutingKey().intern(); - } - } - else - { - queue = queueRegistry.getQueue(body.getQueue()); - routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern(); - } - - if (queue == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); - } - final String exchangeName = body.getExchange() == null ? null : body.getExchange().toString(); - final Exchange exch = virtualHost.getExchange(exchangeName); - if (exch == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist."); - } - - - try - { - if (queue.isExclusive() && !queue.isDurable()) - { - AMQSessionModel session = queue.getExclusiveOwningSession(); - if (session == null || session.getConnectionModel() != protocolConnection) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); - } - } - - if (!exch.isBound(routingKey, body.getArguments(), queue)) - { - String bindingKey = String.valueOf(routingKey); - Map arguments = FieldTable.convertToMap(body.getArguments()); - - if(!exch.addBinding(bindingKey, queue, arguments)) - { - Binding oldBinding = exch.getBinding(bindingKey, queue, arguments); - - Map oldArgs = oldBinding.getArguments(); - if((oldArgs == null && !arguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(arguments))) - { - exch.replaceBinding(oldBinding.getId(), bindingKey, queue, arguments); - } - } - } - } - catch (AMQException e) - { - throw body.getChannelException(AMQConstant.CHANNEL_ERROR, e.toString()); - } - - if (_log.isInfoEnabled()) - { - _log.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey); - } - if (!body.getNowait()) - { - channel.sync(); - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody(); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java deleted file mode 100644 index 035bf25e04..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ /dev/null @@ -1,249 +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.handler; - -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.framing.MethodRegistry; -import org.apache.qpid.framing.QueueDeclareBody; -import org.apache.qpid.framing.QueueDeclareOkBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -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.store.DurableConfigurationStoreHelper; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.util.Map; -import java.util.UUID; - -public class QueueDeclareHandler implements StateAwareMethodListener -{ - private static final Logger _logger = Logger.getLogger(QueueDeclareHandler.class); - - private static final QueueDeclareHandler _instance = new QueueDeclareHandler(); - - public static QueueDeclareHandler getInstance() - { - return _instance; - } - - public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException - { - final AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); - final AMQSessionModel session = protocolConnection.getChannel(channelId); - VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - - final AMQShortString queueName; - - // if we aren't given a queue name, we create one which we return to the client - if ((body.getQueue() == null) || (body.getQueue().length() == 0)) - { - queueName = createName(); - } - else - { - queueName = body.getQueue().intern(); - } - - AMQQueue queue; - - //TODO: do we need to check that the queue already exists with exactly the same "configuration"? - - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - synchronized (queueRegistry) - { - queue = queueRegistry.getQueue(queueName); - - AMQSessionModel owningSession = null; - - if (queue != null) - { - owningSession = queue.getExclusiveOwningSession(); - } - - if (queue == null) - { - if (body.getPassive()) - { - String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; - throw body.getChannelException(AMQConstant.NOT_FOUND, msg); - } - else - { - queue = createQueue(queueName, body, virtualHost, protocolConnection); - queue.setAuthorizationHolder(protocolConnection); - if (queue.isDurable() && !queue.isAutoDelete()) - { - DurableConfigurationStoreHelper.createQueue(store, queue, body.getArguments()); - } - if(body.getAutoDelete()) - { - queue.setDeleteOnNoConsumers(true); - } - queueRegistry.registerQueue(queue); - if (body.getExclusive()) - { - queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId)); - queue.setAuthorizationHolder(protocolConnection); - - if(!body.getDurable()) - { - final AMQQueue q = queue; - final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task() - { - public void doTask(AMQProtocolSession session) throws AMQException - { - q.setExclusiveOwningSession(null); - } - }; - protocolConnection.addSessionCloseTask(sessionCloseTask); - queue.addQueueDeleteTask(new AMQQueue.Task() { - public void doTask(AMQQueue queue) throws AMQException - { - protocolConnection.removeSessionCloseTask(sessionCloseTask); - } - }); - } - } - } - } - else if (queue.isExclusive() && !queue.isDurable() && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); - } - else if(!body.getPassive() && ((queue.isExclusive()) != body.getExclusive())) - { - - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different exclusivity (was: " - + queue.isExclusive() + " requested " + body.getExclusive() + ")"); - } - else if (!body.getPassive() && body.getExclusive() && !(queue.isDurable() ? String.valueOf(queue.getOwner()).equals(session.getClientID()) : (owningSession == null || owningSession.getConnectionModel() == protocolConnection))) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "'), " - + "as exclusive queue with same name " - + "declared on another client ID('" - + queue.getOwner() + "') your clientID('" + session.getClientID() + "')"); - - } - else if(!body.getPassive() && queue.isAutoDelete() != body.getAutoDelete()) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different auto-delete (was: " - + queue.isAutoDelete() + " requested " + body.getAutoDelete() + ")"); - } - else if(!body.getPassive() && queue.isDurable() != body.getDurable()) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different durability (was: " - + queue.isDurable() + " requested " + body.getDurable() + ")"); - } - - - - //set this as the default queue on the channel: - channel.setDefaultQueue(queue); - } - - if (!body.getNowait()) - { - channel.sync(); - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - QueueDeclareOkBody responseBody = - methodRegistry.createQueueDeclareOkBody(queueName, - queue.getMessageCount(), - queue.getConsumerCount()); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - _logger.info("Queue " + queueName + " declared successfully"); - } - } - - protected AMQShortString createName() - { - return new AMQShortString("tmp_" + UUID.randomUUID()); - } - - protected AMQQueue createQueue(final AMQShortString queueName, - QueueDeclareBody body, - VirtualHost virtualHost, - final AMQProtocolSession session) - throws AMQException - { - final QueueRegistry registry = virtualHost.getQueueRegistry(); - String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null; - - Map arguments = FieldTable.convertToMap(body.getArguments()); - String queueNameString = AMQShortString.toString(queueName); - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()), - queueNameString, body.getDurable(), owner, body.getAutoDelete(), - body.getExclusive(),virtualHost, arguments); - - if (body.getExclusive() && !body.getDurable()) - { - final AMQProtocolSession.Task deleteQueueTask = - new AMQProtocolSession.Task() - { - public void doTask(AMQProtocolSession session) throws AMQException - { - if (registry.getQueue(queueName) == queue) - { - queue.delete(); - } - } - }; - - session.addSessionCloseTask(deleteQueueTask); - - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) - { - session.removeSessionCloseTask(deleteQueueTask); - } - }); - } - - return queue; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java deleted file mode 100644 index 4b00c1a09b..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java +++ /dev/null @@ -1,128 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.QueueDeleteBody; -import org.apache.qpid.framing.QueueDeleteOkBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -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.store.DurableConfigurationStore; -import org.apache.qpid.server.store.DurableConfigurationStoreHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class QueueDeleteHandler implements StateAwareMethodListener -{ - private static final QueueDeleteHandler _instance = new QueueDeleteHandler(); - - public static QueueDeleteHandler getInstance() - { - return _instance; - } - - private final boolean _failIfNotFound; - - public QueueDeleteHandler() - { - this(true); - } - - public QueueDeleteHandler(boolean failIfNotFound) - { - _failIfNotFound = failIfNotFound; - - } - - public void methodReceived(AMQStateManager stateManager, QueueDeleteBody body, int channelId) throws AMQException - { - AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); - VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - - - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.sync(); - AMQQueue queue; - if (body.getQueue() == null) - { - - //get the default queue on the channel: - queue = channel.getDefaultQueue(); - } - else - { - queue = queueRegistry.getQueue(body.getQueue()); - } - - if (queue == null) - { - if (_failIfNotFound) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); - } - } - else - { - if (body.getIfEmpty() && !queue.isEmpty()) - { - throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty."); - } - else if (body.getIfUnused() && !queue.isUnused()) - { - // TODO - Error code - throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used."); - } - else - { - AMQSessionModel session = queue.getExclusiveOwningSession(); - if (queue.isExclusive() && !queue.isDurable() && (session == null || session.getConnectionModel() != protocolConnection)) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); - } - - int purged = queue.delete(); - - if (queue.isDurable()) - { - DurableConfigurationStoreHelper.removeQueue(store, queue); - } - - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - } - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java deleted file mode 100644 index 217a264793..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java +++ /dev/null @@ -1,120 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.QueuePurgeBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -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; - -public class QueuePurgeHandler implements StateAwareMethodListener -{ - 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 protocolConnection = stateManager.getProtocolSession(); - VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - - AMQChannel channel = protocolConnection.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - AMQQueue queue; - if(body.getQueue() == null) - { - - //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 - { - AMQSessionModel session = queue.getExclusiveOwningSession(); - - if (queue.isExclusive() && (session == null || session.getConnectionModel() != protocolConnection)) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue is exclusive, but not created on this Connection."); - } - - long purged = queue.clearQueue(); - - - if(!body.getNowait()) - { - channel.sync(); - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - } - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java deleted file mode 100644 index e0e814537a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java +++ /dev/null @@ -1,138 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.QueueUnbindBody; -import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; -import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -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.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class QueueUnbindHandler implements StateAwareMethodListener -{ - private static final Logger _log = Logger.getLogger(QueueUnbindHandler.class); - - private static final QueueUnbindHandler _instance = new QueueUnbindHandler(); - - public static QueueUnbindHandler getInstance() - { - return _instance; - } - - private QueueUnbindHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, QueueUnbindBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - VirtualHost virtualHost = session.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - - - final AMQQueue queue; - final AMQShortString routingKey; - - - AMQChannel channel = session.getChannel(channelId); - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - if (body.getQueue() == null) - { - - queue = channel.getDefaultQueue(); - - if (queue == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "No default queue defined on channel and queue was null"); - } - - routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); - - } - else - { - queue = queueRegistry.getQueue(body.getQueue()); - routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); - } - - if (queue == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); - } - final Exchange exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString()); - if (exch == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist."); - } - - if(exch.getBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(body.getArguments())) == null) - { - throw body.getChannelException(AMQConstant.NOT_FOUND,"No such binding"); - } - else - { - exch.removeBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(body.getArguments())); - } - - - if (_log.isInfoEnabled()) - { - _log.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey); - } - - final MethodRegistry registry = session.getMethodRegistry(); - final AMQMethodBody responseBody; - if (registry instanceof MethodRegistry_0_9) - { - responseBody = ((MethodRegistry_0_9)registry).createQueueUnbindOkBody(); - } - else if (registry instanceof MethodRegistry_0_91) - { - responseBody = ((MethodRegistry_0_91)registry).createQueueUnbindOkBody(); - } - else - { - // 0-8 does not support QueueUnbind - throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + session.getProtocolVersion(), null); - } - channel.sync(); - session.writeFrame(responseBody.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java deleted file mode 100644 index 3b6dc3f3f5..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java +++ /dev/null @@ -1,574 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.*; -import org.apache.qpid.server.state.AMQStateManager; - -import java.util.HashMap; -import java.util.Map; - -public class ServerMethodDispatcherImpl implements MethodDispatcher -{ - private final AMQStateManager _stateManager; - - private static interface DispatcherFactory - { - public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager); - } - - private static final Map _dispatcherFactories = - new HashMap(); - - - 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); - } - }); - _dispatcherFactories.put(ProtocolVersion.v0_91, - new DispatcherFactory() - { - public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager) - { - return new ServerMethodDispatcherImpl_0_91(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/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java deleted file mode 100644 index 7ce8664d37..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java +++ /dev/null @@ -1,164 +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.handler; - - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.*; -import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9; -import org.apache.qpid.server.state.AMQStateManager; - - - -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/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java deleted file mode 100644 index 126e1484b6..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java +++ /dev/null @@ -1,168 +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.handler; - - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.*; -import org.apache.qpid.framing.amqp_0_91.MethodDispatcher_0_91; -import org.apache.qpid.server.state.AMQStateManager; - - -public class ServerMethodDispatcherImpl_0_91 - extends ServerMethodDispatcherImpl - implements MethodDispatcher_0_91 - -{ - - private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler = - BasicRecoverSyncMethodHandler.getInstance(); - private static final QueueUnbindHandler _queueUnbindHandler = - QueueUnbindHandler.getInstance(); - - - public ServerMethodDispatcherImpl_0_91(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 dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - 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; - } -} \ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java deleted file mode 100644 index fabd2a5ccf..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java +++ /dev/null @@ -1,95 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.BasicRecoverOkBody; -import org.apache.qpid.framing.ChannelAlertBody; -import org.apache.qpid.framing.TestContentBody; -import org.apache.qpid.framing.TestContentOkBody; -import org.apache.qpid.framing.TestIntegerBody; -import org.apache.qpid.framing.TestIntegerOkBody; -import org.apache.qpid.framing.TestStringBody; -import org.apache.qpid.framing.TestStringOkBody; -import org.apache.qpid.framing.TestTableBody; -import org.apache.qpid.framing.TestTableOkBody; -import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0; -import org.apache.qpid.server.state.AMQStateManager; - -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/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java deleted file mode 100644 index afa5fdb72a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java +++ /dev/null @@ -1,85 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.TxCommitBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class TxCommitHandler implements StateAwareMethodListener -{ - private static final Logger _log = Logger.getLogger(TxCommitHandler.class); - - private static TxCommitHandler _instance = new TxCommitHandler(); - - public static TxCommitHandler getInstance() - { - return _instance; - } - - private TxCommitHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, TxCommitBody body, final int channelId) throws AMQException - { - final AMQProtocolSession session = stateManager.getProtocolSession(); - - try - { - if (_log.isDebugEnabled()) - { - _log.debug("Commit received on channel " + channelId); - } - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - channel.commit(new Runnable() - { - - @Override - public void run() - { - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); - } - }, true); - - - - } - catch (AMQException e) - { - throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage()); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java deleted file mode 100644 index 010a07be14..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java +++ /dev/null @@ -1,85 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.TxRollbackBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class TxRollbackHandler implements StateAwareMethodListener -{ - private static TxRollbackHandler _instance = new TxRollbackHandler(); - - public static TxRollbackHandler getInstance() - { - return _instance; - } - - private TxRollbackHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, final int channelId) throws AMQException - { - final AMQProtocolSession session = stateManager.getProtocolSession(); - - try - { - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - - - final MethodRegistry methodRegistry = session.getMethodRegistry(); - final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody(); - - Runnable task = new Runnable() - { - - public void run() - { - session.writeFrame(responseBody.generateFrame(channelId)); - } - }; - - channel.rollback(task); - - //Now resend all the unacknowledged messages back to the original subscribers. - //(Must be done after the TxnRollback-ok response). - // Why, are we not allowed to send messages back to client before the ok method? - channel.resend(false); - - } - catch (AMQException e) - { - throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage()); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java deleted file mode 100644 index 44b47704d8..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java +++ /dev/null @@ -1,62 +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.handler; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.TxSelectBody; -import org.apache.qpid.framing.TxSelectOkBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; - -public class TxSelectHandler implements StateAwareMethodListener -{ - private static TxSelectHandler _instance = new TxSelectHandler(); - - public static TxSelectHandler getInstance() - { - return _instance; - } - - private TxSelectHandler() - { - } - - public void methodReceived(AMQStateManager stateManager, TxSelectBody body, int channelId) throws AMQException - { - AMQProtocolSession session = stateManager.getProtocolSession(); - - AMQChannel channel = session.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - channel.setLocalTransactional(); - - MethodRegistry methodRegistry = session.getMethodRegistry(); - TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java deleted file mode 100644 index cfc52c558c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.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.qpid.server.handler; - - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; - -public class UnexpectedMethodException extends AMQException -{ - - private static final long serialVersionUID = -255921574946294892L; - - public UnexpectedMethodException(AMQMethodBody body) - { - super("Unexpected method recevied: " + body.getClass().getName()); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java index 50a7e67583..da280af059 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java index bcb9cb2ac4..0ff26a64b6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java @@ -20,10 +20,10 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ServerSession; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java deleted file mode 100644 index 439d7aa928..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java +++ /dev/null @@ -1,249 +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.message; - -import org.apache.log4j.Logger; - -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.AMQChannel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.store.StoredMessage; - -import java.lang.ref.WeakReference; -import java.nio.ByteBuffer; - -/** - * A deliverable message. - */ -public class AMQMessage extends AbstractServerMessageImpl -{ - /** Used for debugging purposes. */ - private static final Logger _log = Logger.getLogger(AMQMessage.class); - - /** 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 static final byte DELIVERED_TO_CONSUMER = 0x02; - - private byte _flags = 0; - - private long _expiration; - - private final long _size; - - private Object _connectionIdentifier; - private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER); - - public AMQMessage(StoredMessage handle) - { - this(handle, null); - } - - public AMQMessage(StoredMessage handle, WeakReference channelRef) - { - super(handle); - - - final MessageMetaData metaData = handle.getMetaData(); - _size = metaData.getContentSize(); - final MessagePublishInfo messagePublishInfo = metaData.getMessagePublishInfo(); - - if(messagePublishInfo.isImmediate()) - { - _flags |= IMMEDIATE; - } - } - - public void setExpiration(final long expiration) - { - - _expiration = expiration; - - } - - public MessageMetaData getMessageMetaData() - { - return getStoredMessage().getMetaData(); - } - - public ContentHeaderBody getContentHeaderBody() - { - return getMessageMetaData().getContentHeaderBody(); - } - - public Long getMessageId() - { - return getStoredMessage().getMessageNumber(); - } - - /** - * Called selectors to determin if the message has already been sent - * - * @return _deliveredToConsumer - */ - public boolean getDeliveredToConsumer() - { - return (_flags & DELIVERED_TO_CONSUMER) != 0; - } - - public String getRoutingKey() - { - MessageMetaData messageMetaData = getMessageMetaData(); - if (messageMetaData != null) - { - AMQShortString routingKey = messageMetaData.getMessagePublishInfo().getRoutingKey(); - if (routingKey != null) - { - return routingKey.asString(); - } - } - return null; - } - - public AMQMessageHeader getMessageHeader() - { - return getMessageMetaData().getMessageHeader(); - } - - public boolean isPersistent() - { - return getMessageMetaData().isPersistent(); - } - - /** - * Called to enforce the 'immediate' flag. - * - * @returns true if the message is marked for immediate delivery but has not been marked as delivered - * to a consumer - */ - public boolean immediateAndNotDelivered() - { - - return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE; - - } - - public MessagePublishInfo getMessagePublishInfo() throws AMQException - { - return getMessageMetaData().getMessagePublishInfo(); - } - - public long getArrivalTime() - { - return getMessageMetaData().getArrivalTime(); - } - - /** - * Checks to see if the message has expired. If it has the message is dequeued. - * - * @param queue The queue to check the expiration against. (Currently not used) - * - * @return true if the message has expire - * - * @throws AMQException - */ - public boolean expired(AMQQueue queue) throws AMQException - { - - if (_expiration != 0L) - { - long now = System.currentTimeMillis(); - - return (now > _expiration); - } - - return false; - } - - /** - * Called when this message is delivered to a consumer. (used to implement the 'immediate' flag functionality). - * And for selector efficiency. - */ - public void setDeliveredToConsumer() - { - _flags |= DELIVERED_TO_CONSUMER; - } - - public long getSize() - { - return _size; - - } - - public boolean isImmediate() - { - return (_flags & IMMEDIATE) == IMMEDIATE; - } - - public long getExpiration() - { - return _expiration; - } - - public MessageReference newReference() - { - return new AMQMessageReference(this); - } - - public long getMessageNumber() - { - return getStoredMessage().getMessageNumber(); - } - - - public Object getConnectionIdentifier() - { - return _connectionIdentifier; - - } - - public void setConnectionIdentifier(final Object connectionIdentifier) - { - _connectionIdentifier = connectionIdentifier; - } - - - public String toString() - { - return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + getReferenceCount(); - } - - public int getContent(ByteBuffer buf, int offset) - { - return getStoredMessage().getContent(offset, buf); - } - - - public ByteBuffer getContent(int offset, int size) - { - return getStoredMessage().getContent(offset, size); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java deleted file mode 100644 index 62cfa8431c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java +++ /dev/null @@ -1,41 +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.message; - -public class AMQMessageReference extends MessageReference -{ - - - public AMQMessageReference(AMQMessage message) - { - super(message); - } - - protected void onReference(AMQMessage message) - { - message.incrementReference(); - } - - protected void onRelease(AMQMessage message) - { - message.decrementReference(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java deleted file mode 100644 index 01c1021070..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ /dev/null @@ -1,145 +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.message; - -import java.util.Collection; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; - -import java.util.Set; - -public class ContentHeaderBodyAdapter implements AMQMessageHeader -{ - private final ContentHeaderBody _contentHeaderBody; - - public ContentHeaderBodyAdapter(ContentHeaderBody contentHeaderBody) - { - _contentHeaderBody = contentHeaderBody; - } - - private BasicContentHeaderProperties getProperties() - { - return (BasicContentHeaderProperties) _contentHeaderBody.getProperties(); - } - - public String getCorrelationId() - { - return getProperties().getCorrelationIdAsString(); - } - - public long getExpiration() - { - return getProperties().getExpiration(); - } - - public String getUserId() - { - return getProperties().getUserIdAsString(); - } - - public String getAppId() - { - return getProperties().getAppIdAsString(); - } - - public String getMessageId() - { - return getProperties().getMessageIdAsString(); - } - - public String getMimeType() - { - return getProperties().getContentTypeAsString(); - } - - public String getEncoding() - { - return getProperties().getEncodingAsString(); - } - - public byte getPriority() - { - return getProperties().getPriority(); - } - - public long getTimestamp() - { - return getProperties().getTimestamp(); - } - - public String getType() - { - return getProperties().getTypeAsString(); - } - - public String getReplyTo() - { - return getProperties().getReplyToAsString(); - } - - public String getReplyToExchange() - { - // TODO - return getReplyTo(); - } - - public String getReplyToRoutingKey() - { - // TODO - return getReplyTo(); - - } - - public Object getHeader(String name) - { - FieldTable ft = getProperties().getHeaders(); - return ft.get(name); - } - - public boolean containsHeaders(Set names) - { - FieldTable ft = getProperties().getHeaders(); - for(String name : names) - { - if(!ft.containsKey(name)) - { - return false; - } - } - return true; - } - - @Override - public Collection getHeaderNames() - { - FieldTable ft = getProperties().getHeaders(); - return ft.keys(); - } - - public boolean containsHeader(String name) - { - FieldTable ft = getProperties().getHeaders(); - return ft.containsKey(name); - } - - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java deleted file mode 100644 index e890bf5ef8..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java +++ /dev/null @@ -1,347 +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.message; - -import java.util.Collection; -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.EncodingUtils; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.store.MessageMetaDataType; -import org.apache.qpid.server.store.StorableMessageMetaData; -import org.apache.qpid.server.util.ByteBufferOutputStream; -import org.apache.qpid.util.ByteBufferInputStream; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Set; - -/** - * Encapsulates a publish body and a content header. In the context of the message store these are treated as a - * single unit. - */ -public class MessageMetaData implements StorableMessageMetaData -{ - private MessagePublishInfo _messagePublishInfo; - - private ContentHeaderBody _contentHeaderBody; - - private int _contentChunkCount; - - private long _arrivalTime; - private static final byte MANDATORY_FLAG = 1; - private static final byte IMMEDIATE_FLAG = 2; - public static final MessageMetaDataType.Factory FACTORY = new MetaDataFactory(); - - public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount) - { - this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis()); - } - - public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime) - { - _contentHeaderBody = contentHeaderBody; - _messagePublishInfo = publishBody; - _contentChunkCount = contentChunkCount; - _arrivalTime = arrivalTime; - } - - public int getContentChunkCount() - { - return _contentChunkCount; - } - - public void setContentChunkCount(int contentChunkCount) - { - _contentChunkCount = contentChunkCount; - } - - public ContentHeaderBody getContentHeaderBody() - { - return _contentHeaderBody; - } - - public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) - { - _contentHeaderBody = contentHeaderBody; - } - - public MessagePublishInfo getMessagePublishInfo() - { - return _messagePublishInfo; - } - - public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo) - { - _messagePublishInfo = messagePublishInfo; - } - - public long getArrivalTime() - { - return _arrivalTime; - } - - public void setArrivalTime(long arrivalTime) - { - _arrivalTime = arrivalTime; - } - - public MessageMetaDataType getType() - { - return MessageMetaDataType.META_DATA_0_8; - } - - public int getStorableSize() - { - int size = _contentHeaderBody.getSize(); - size += 4; - size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getExchange()); - size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getRoutingKey()); - size += 1; // flags for immediate/mandatory - size += EncodingUtils.encodedLongLength(); - - return size; - } - - - public int writeToBuffer(int offset, ByteBuffer dest) - { - int oldPosition = dest.position(); - try - { - - DataOutputStream dataOutputStream = new DataOutputStream(new ByteBufferOutputStream(dest)); - EncodingUtils.writeInteger(dataOutputStream, _contentHeaderBody.getSize()); - _contentHeaderBody.writePayload(dataOutputStream); - EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getExchange()); - EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getRoutingKey()); - byte flags = 0; - if(_messagePublishInfo.isMandatory()) - { - flags |= MANDATORY_FLAG; - } - if(_messagePublishInfo.isImmediate()) - { - flags |= IMMEDIATE_FLAG; - } - dest.put(flags); - dest.putLong(_arrivalTime); - - } - catch (IOException e) - { - // This shouldn't happen as we are not actually using anything that can throw an IO Exception - throw new RuntimeException(e); - } - - return dest.position()-oldPosition; - } - - public int getContentSize() - { - return (int) _contentHeaderBody.getBodySize(); - } - - public boolean isPersistent() - { - BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.getProperties()); - return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT; - } - - private static class MetaDataFactory implements MessageMetaDataType.Factory - { - - - public MessageMetaData createMetaData(ByteBuffer buf) - { - try - { - ByteBufferInputStream bbis = new ByteBufferInputStream(buf); - DataInputStream dais = new DataInputStream(bbis); - int size = EncodingUtils.readInteger(dais); - ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(dais, size); - final AMQShortString exchange = EncodingUtils.readAMQShortString(dais); - final AMQShortString routingKey = EncodingUtils.readAMQShortString(dais); - - final byte flags = EncodingUtils.readByte(dais); - long arrivalTime = EncodingUtils.readLong(dais); - - MessagePublishInfo publishBody = - new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return exchange; - } - - public void setExchange(AMQShortString exchange) - { - } - - public boolean isImmediate() - { - return (flags & IMMEDIATE_FLAG) != 0; - } - - public boolean isMandatory() - { - return (flags & MANDATORY_FLAG) != 0; - } - - public AMQShortString getRoutingKey() - { - return routingKey; - } - }; - return new MessageMetaData(publishBody, chb, 0, arrivalTime); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - - } - }; - - public AMQMessageHeader getMessageHeader() - { - return new MessageHeaderAdapter(); - } - - private final class MessageHeaderAdapter implements AMQMessageHeader - { - private BasicContentHeaderProperties getProperties() - { - return (BasicContentHeaderProperties) getContentHeaderBody().getProperties(); - } - - public String getUserId() - { - return getProperties().getUserIdAsString(); - } - - public String getAppId() - { - return getProperties().getAppIdAsString(); - } - - public String getCorrelationId() - { - return getProperties().getCorrelationIdAsString(); - } - - public long getExpiration() - { - return getProperties().getExpiration(); - } - - public String getMessageId() - { - return getProperties().getMessageIdAsString(); - } - - public String getMimeType() - { - return getProperties().getContentTypeAsString(); - } - - public String getEncoding() - { - return getProperties().getEncodingAsString(); - } - - public byte getPriority() - { - return getProperties().getPriority(); - } - - public long getTimestamp() - { - return getProperties().getTimestamp(); - } - - public String getType() - { - return getProperties().getTypeAsString(); - } - - public String getReplyTo() - { - return getProperties().getReplyToAsString(); - } - - public String getReplyToExchange() - { - // TODO - return getReplyTo(); - } - - public String getReplyToRoutingKey() - { - // TODO - return getReplyTo(); - } - - public Object getHeader(String name) - { - FieldTable ft = getProperties().getHeaders(); - return ft.get(name); - } - - public boolean containsHeaders(Set names) - { - FieldTable ft = getProperties().getHeaders(); - for(String name : names) - { - if(!ft.containsKey(name)) - { - return false; - } - } - return true; - } - - @Override - public Collection getHeaderNames() - { - return getProperties().getHeaders().keys(); - } - - public boolean containsHeader(String name) - { - FieldTable ft = getProperties().getHeaders(); - return ft.containsKey(name); - } - - - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java deleted file mode 100755 index 88b0f60346..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.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.qpid.server.message; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.store.MessageMetaDataType; -import org.apache.qpid.server.store.StorableMessageMetaData; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.Header; -import org.apache.qpid.transport.MessageDeliveryMode; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Struct; -import org.apache.qpid.transport.codec.BBDecoder; -import org.apache.qpid.transport.codec.BBEncoder; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMessage -{ - private Header _header; - private DeliveryProperties _deliveryProps; - private MessageProperties _messageProps; - private MessageTransferHeader _messageHeader; - private long _arrivalTime; - private int _bodySize; - - private static final int ENCODER_SIZE = 1 << 10; - - public static final MessageMetaDataType.Factory FACTORY = new MetaDataFactory(); - - private volatile ByteBuffer _encoded; - private Object _connectionReference; - - - public MessageMetaData_0_10(MessageTransfer xfr) - { - this(xfr.getHeader(), xfr.getBodySize(), System.currentTimeMillis()); - } - - private MessageMetaData_0_10(Header header, int bodySize, long arrivalTime) - { - _header = header; - if(_header != null) - { - _deliveryProps = _header.getDeliveryProperties(); - _messageProps = _header.getMessageProperties(); - } - else - { - _deliveryProps = null; - _messageProps = null; - } - _messageHeader = new MessageTransferHeader(_deliveryProps, _messageProps); - _arrivalTime = arrivalTime; - _bodySize = bodySize; - - } - - - - public MessageMetaDataType getType() - { - return MessageMetaDataType.META_DATA_0_10; - } - - public int getStorableSize() - { - ByteBuffer buf = _encoded; - - if(buf == null) - { - buf = encodeAsBuffer(); - _encoded = buf; - } - - //TODO -- need to add stuff - return buf.limit(); - } - - private ByteBuffer encodeAsBuffer() - { - BBEncoder encoder = new BBEncoder(ENCODER_SIZE); - - encoder.writeInt64(_arrivalTime); - encoder.writeInt32(_bodySize); - int headersLength = 0; - if(_header.getDeliveryProperties() != null) - { - headersLength++; - } - if(_header.getMessageProperties() != null) - { - headersLength++; - } - if(_header.getNonStandardProperties() != null) - { - headersLength += _header.getNonStandardProperties().size(); - } - - encoder.writeInt32(headersLength); - - if(_header.getDeliveryProperties() != null) - { - encoder.writeStruct32(_header.getDeliveryProperties()); - } - if(_header.getMessageProperties() != null) - { - encoder.writeStruct32(_header.getMessageProperties()); - } - if(_header.getNonStandardProperties() != null) - { - - for(Struct header : _header.getNonStandardProperties()) - { - encoder.writeStruct32(header); - } - - } - ByteBuffer buf = encoder.buffer(); - return buf; - } - - public int writeToBuffer(int offsetInMetaData, ByteBuffer dest) - { - ByteBuffer buf = _encoded; - - if(buf == null) - { - buf = encodeAsBuffer(); - _encoded = buf; - } - - buf = buf.duplicate(); - - buf.position(offsetInMetaData); - - if(dest.remaining() < buf.limit()) - { - buf.limit(dest.remaining()); - } - dest.put(buf); - return buf.limit(); - } - - public int getContentSize() - { - return _bodySize; - } - - public boolean isPersistent() - { - return _deliveryProps == null ? false : _deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT; - } - - public String getRoutingKey() - { - return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); - } - - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(getRoutingKey()); - } - - public AMQMessageHeader getMessageHeader() - { - return _messageHeader; - } - - public long getSize() - { - - return _bodySize; - } - - public boolean isImmediate() - { - return _deliveryProps != null && _deliveryProps.getImmediate(); - } - - public long getExpiration() - { - return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); - } - - public boolean isRedelivered() - { - // The *Message* is never redelivered, only queue entries are... - return false; - } - - public long getArrivalTime() - { - return _arrivalTime; - } - - public Header getHeader() - { - return _header; - } - - public void setConnectionReference(Object connectionReference) - { - _connectionReference = connectionReference; - } - - public Object getConnectionReference() - { - return _connectionReference; - } - - private static class MetaDataFactory implements MessageMetaDataType.Factory - { - public MessageMetaData_0_10 createMetaData(ByteBuffer buf) - { - BBDecoder decoder = new BBDecoder(); - decoder.init(buf); - - long arrivalTime = decoder.readInt64(); - int bodySize = decoder.readInt32(); - int headerCount = decoder.readInt32(); - - DeliveryProperties deliveryProperties = null; - MessageProperties messageProperties = null; - List otherProps = null; - - for(int i = 0 ; i < headerCount; i++) - { - Struct struct = decoder.readStruct32(); - if(struct instanceof DeliveryProperties && deliveryProperties == null) - { - deliveryProperties = (DeliveryProperties) struct; - } - else if(struct instanceof MessageProperties && messageProperties == null) - { - messageProperties = (MessageProperties) struct; - } - else - { - if(otherProps == null) - { - otherProps = new ArrayList(); - - } - otherProps.add(struct); - } - } - Header header = new Header(deliveryProperties,messageProperties,otherProps); - - return new MessageMetaData_0_10(header, bodySize, arrivalTime); - - } - } - - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java deleted file mode 100644 index 91384f7c22..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ /dev/null @@ -1,170 +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.message; - -import java.util.*; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.MessageDeliveryPriority; -import org.apache.qpid.transport.MessageProperties; - -class MessageTransferHeader implements AMQMessageHeader -{ - - - public static final String JMS_TYPE = "x-jms-type"; - - private final DeliveryProperties _deliveryProps; - private final MessageProperties _messageProps; - - public MessageTransferHeader(DeliveryProperties deliveryProps, MessageProperties messageProps) - { - _deliveryProps = deliveryProps; - _messageProps = messageProps; - } - - public String getCorrelationId() - { - if (_messageProps != null && _messageProps.getCorrelationId() != null) - { - return new String(_messageProps.getCorrelationId()); - } - else - { - return null; - } - } - - public long getExpiration() - { - return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); - } - - public String getUserId() - { - byte[] userIdBytes = _messageProps == null ? null : _messageProps.getUserId(); - return userIdBytes == null ? null : new String(userIdBytes); - } - - public String getAppId() - { - byte[] appIdBytes = _messageProps == null ? null : _messageProps.getAppId(); - return appIdBytes == null ? null : new String(appIdBytes); - } - - public String getMessageId() - { - UUID id = _messageProps == null ? null : _messageProps.getMessageId(); - - return id == null ? null : String.valueOf(id); - } - - public String getMimeType() - { - return _messageProps == null ? null : _messageProps.getContentType(); - } - - public String getEncoding() - { - return _messageProps == null ? null : _messageProps.getContentEncoding(); - } - - public byte getPriority() - { - MessageDeliveryPriority priority = _deliveryProps == null || !_deliveryProps.hasPriority() - ? MessageDeliveryPriority.MEDIUM - : _deliveryProps.getPriority(); - return (byte) priority.getValue(); - } - - public long getTimestamp() - { - return _deliveryProps == null ? 0L : _deliveryProps.getTimestamp(); - } - - public String getType() - { - Object type = getHeader(JMS_TYPE); - return type instanceof String ? (String) type : null; - } - - public String getReplyTo() - { - if (_messageProps != null && _messageProps.getReplyTo() != null) - { - return _messageProps.getReplyTo().toString(); - } - else - { - return null; - } - } - - public String getReplyToExchange() - { - if (_messageProps != null && _messageProps.getReplyTo() != null) - { - return _messageProps.getReplyTo().getExchange(); - } - else - { - return null; - } - } - - public String getReplyToRoutingKey() - { - if (_messageProps != null && _messageProps.getReplyTo() != null) - { - return _messageProps.getReplyTo().getRoutingKey(); - } - else - { - return null; - } - } - - public Object getHeader(String name) - { - Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); - return appHeaders == null ? null : appHeaders.get(name); - } - - public boolean containsHeaders(Set names) - { - Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); - return appHeaders != null && appHeaders.keySet().containsAll(names); - - } - - @Override - public Collection getHeaderNames() - { - Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); - return appHeaders != null ? Collections.unmodifiableCollection(appHeaders.keySet()) : Collections.EMPTY_SET ; - - } - - public boolean containsHeader(String name) - { - Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); - return appHeaders != null && appHeaders.containsKey(name); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java deleted file mode 100644 index 8350eccec1..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java +++ /dev/null @@ -1,132 +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.message; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.transport.Header; - -import java.nio.ByteBuffer; - - -public class MessageTransferMessage extends AbstractServerMessageImpl implements InboundMessage -{ - - private Object _connectionRef; - - public MessageTransferMessage(StoredMessage storeMessage, Object connectionRef) - { - super(storeMessage); - _connectionRef = connectionRef; - } - - private MessageMetaData_0_10 getMetaData() - { - return getStoredMessage().getMetaData(); - } - - public String getRoutingKey() - { - return getMetaData().getRoutingKey(); - } - - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(getRoutingKey()); - } - - public AMQMessageHeader getMessageHeader() - { - return getMetaData().getMessageHeader(); - } - - public boolean isPersistent() - { - return getMetaData().isPersistent(); - } - - - public boolean isRedelivered() - { - // The *Message* is never redelivered, only queue entries are... this is here so that filters - // can run against the message on entry to an exchange - return false; - } - - public long getSize() - { - - return getMetaData().getSize(); - } - - public boolean isImmediate() - { - return getMetaData().isImmediate(); - } - - public long getExpiration() - { - return getMetaData().getExpiration(); - } - - public MessageReference newReference() - { - return new TransferMessageReference(this); - } - - public long getMessageNumber() - { - return getStoredMessage().getMessageNumber(); - } - - public long getArrivalTime() - { - return getMetaData().getArrivalTime(); - } - - public int getContent(ByteBuffer buf, int offset) - { - return getStoredMessage().getContent(offset, buf); - } - - - public ByteBuffer getContent(int offset, int size) - { - return getStoredMessage().getContent(offset,size); - } - - public Header getHeader() - { - return getMetaData().getHeader(); - } - - public ByteBuffer getBody() - { - - return getContent(0, (int)getSize()); - } - - public Object getConnectionReference() - { - return _connectionRef; - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java deleted file mode 100644 index cb44f80b91..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java +++ /dev/null @@ -1,39 +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.message; - -public class TransferMessageReference extends MessageReference -{ - public TransferMessageReference(MessageTransferMessage message) - { - super(message); - } - - protected void onReference(MessageTransferMessage message) - { - message.incrementReference(); - } - - protected void onRelease(MessageTransferMessage message) - { - message.decrementReference(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java deleted file mode 100755 index 0c14c06624..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java +++ /dev/null @@ -1,149 +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.output; - -import org.apache.qpid.AMQPInvalidClassException; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.Header; -import org.apache.qpid.transport.MessageDeliveryMode; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.ReplyTo; - -import java.util.HashMap; -import java.util.Map; - -public class HeaderPropertiesConverter -{ - private HeaderPropertiesConverter() - { - } - - public static BasicContentHeaderProperties convert(MessageTransferMessage messageTransferMessage, VirtualHost vhost) - { - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - - Header header = messageTransferMessage.getHeader(); - DeliveryProperties deliveryProps = header.getDeliveryProperties(); - MessageProperties messageProps = header.getMessageProperties(); - - if(deliveryProps != null) - { - if(deliveryProps.hasDeliveryMode()) - { - props.setDeliveryMode((byte)(deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT)); - } - if(deliveryProps.hasExpiration()) - { - props.setExpiration(deliveryProps.getExpiration()); - } - if(deliveryProps.hasPriority()) - { - props.setPriority((byte)deliveryProps.getPriority().getValue()); - } - if(deliveryProps.hasTimestamp()) - { - props.setTimestamp(deliveryProps.getTimestamp()); - } - } - if(messageProps != null) - { - if(messageProps.hasAppId()) - { - props.setAppId(new AMQShortString(messageProps.getAppId())); - } - if(messageProps.hasContentType()) - { - props.setContentType(messageProps.getContentType()); - } - if(messageProps.hasCorrelationId()) - { - props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId())); - } - if(messageProps.hasContentEncoding()) - { - props.setEncoding(messageProps.getContentEncoding()); - } - if(messageProps.hasMessageId()) - { - props.setMessageId("ID:" + messageProps.getMessageId().toString()); - } - if(messageProps.hasReplyTo()) - { - ReplyTo replyTo = messageProps.getReplyTo(); - String exchangeName = replyTo.getExchange(); - String routingKey = replyTo.getRoutingKey(); - if(exchangeName == null) - { - exchangeName = ""; - } - - Exchange exchange = vhost.getExchange(exchangeName); - String exchangeClass = exchange == null ? ExchangeDefaults.DIRECT_EXCHANGE_CLASS.asString() : exchange.getType().getName().asString(); - props.setReplyTo(exchangeClass + "://"+exchangeName+"//?routingkey='"+(routingKey==null ? "" : routingKey+"'")); - - } - if(messageProps.hasUserId()) - { - props.setUserId(new AMQShortString(messageProps.getUserId())); - } - - if(messageProps.hasApplicationHeaders()) - { - Map appHeaders = new HashMap(messageProps.getApplicationHeaders()); - if(messageProps.getApplicationHeaders().containsKey("x-jms-type")) - { - props.setType(String.valueOf(appHeaders.remove("x-jms-type"))); - } - - FieldTable ft = new FieldTable(); - for(Map.Entry entry : appHeaders.entrySet()) - { - try - { - ft.put(new AMQShortString(entry.getKey()), entry.getValue()); - } - catch(AMQPInvalidClassException e) - { - // TODO - // log here, but ignore - just can;t convert - } - } - props.setHeaders(ft); - - } - } - - - - - - - - return props; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java deleted file mode 100644 index 04d81bf2f5..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java +++ /dev/null @@ -1,60 +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. - * - */ - -/* - * 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.AMQException; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.QueueEntry; - -public interface ProtocolOutputConverter -{ - void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag); - - interface Factory - { - ProtocolOutputConverter newInstance(AMQProtocolSession session); - } - - void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) - throws AMQException; - - void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException; - - byte getProtocolMinorVersion(); - - byte getProtocolMajorVersion(); - - void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource msgContent, int channelId, int replyCode, AMQShortString replyText) - throws AMQException; - - void writeFrame(AMQDataBlock block); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java deleted file mode 100644 index 917215a42f..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java +++ /dev/null @@ -1,452 +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.output; - -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.AMQMethodBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicCancelOkBody; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.BasicGetOkBody; -import org.apache.qpid.framing.BasicReturnBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.transport.DeliveryProperties; - -import java.io.DataOutput; -import java.io.IOException; -import java.nio.ByteBuffer; - -class ProtocolOutputConverterImpl implements ProtocolOutputConverter -{ - private static final int BASIC_CLASS_ID = 60; - - private final MethodRegistry _methodRegistry; - private final AMQProtocolSession _protocolSession; - - ProtocolOutputConverterImpl(AMQProtocolSession session, MethodRegistry methodRegistry) - { - _protocolSession = session; - _methodRegistry = methodRegistry; - } - - - public AMQProtocolSession getProtocolSession() - { - return _protocolSession; - } - - public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) - throws AMQException - { - AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag); - writeMessageDelivery(entry, channelId, deliverBody); - } - - - private ContentHeaderBody getContentHeaderBody(QueueEntry entry) - throws AMQException - { - if(entry.getMessage() instanceof AMQMessage) - { - return ((AMQMessage)entry.getMessage()).getContentHeaderBody(); - } - else - { - final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message, entry.getQueue().getVirtualHost()); - ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID); - chb.setBodySize(message.getSize()); - return chb; - } - } - - - private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody) - throws AMQException - { - writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody); - } - - private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody) - throws AMQException - { - - - int bodySize = (int) message.getSize(); - - if(bodySize == 0) - { - SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody, - contentHeaderBody); - - writeFrame(compositeBlock); - } - else - { - int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead(); - - - int capacity = bodySize > maxBodySize ? maxBodySize : bodySize; - - int writtenSize = capacity; - - AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity); - - CompositeAMQBodyBlock - compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody); - writeFrame(compositeBlock); - - while(writtenSize < bodySize) - { - capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize; - MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity); - writtenSize += capacity; - - writeFrame(new AMQFrame(channelId, body)); - } - } - } - - private class MessageContentSourceBody implements AMQBody - { - public static final byte TYPE = 3; - private int _length; - private MessageContentSource _message; - private int _offset; - - public MessageContentSourceBody(MessageContentSource message, int offset, int length) - { - _message = message; - _offset = offset; - _length = length; - } - - public byte getFrameType() - { - return TYPE; - } - - public int getSize() - { - return _length; - } - - public void writePayload(DataOutput buffer) throws IOException - { - ByteBuffer buf = _message.getContent(_offset, _length); - - if(buf.hasArray()) - { - buffer.write(buf.array(), buf.arrayOffset()+buf.position(), buf.remaining()); - } - else - { - - byte[] data = new byte[_length]; - - buf.get(data); - - buffer.write(data); - } - } - - public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException - { - throw new UnsupportedOperationException(); - } - } - - public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException - { - AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); - writeMessageDelivery(entry, channelId, deliver); - } - - - private AMQBody createEncodedDeliverBody(QueueEntry entry, - final long deliveryTag, - final AMQShortString consumerTag) - throws AMQException - { - - final AMQShortString exchangeName; - final AMQShortString routingKey; - - if(entry.getMessage() instanceof AMQMessage) - { - final AMQMessage message = (AMQMessage) entry.getMessage(); - final MessagePublishInfo pb = message.getMessagePublishInfo(); - exchangeName = pb.getExchange(); - routingKey = pb.getRoutingKey(); - } - else - { - MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); - exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); - routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); - } - - final boolean isRedelivered = entry.isRedelivered(); - - final AMQBody returnBlock = new EncodedDeliveryBody(deliveryTag, routingKey, exchangeName, consumerTag, isRedelivered); - return returnBlock; - } - - private class EncodedDeliveryBody implements AMQBody - { - private final long _deliveryTag; - private final AMQShortString _routingKey; - private final AMQShortString _exchangeName; - private final AMQShortString _consumerTag; - private final boolean _isRedelivered; - private AMQBody _underlyingBody; - - private EncodedDeliveryBody(long deliveryTag, AMQShortString routingKey, AMQShortString exchangeName, AMQShortString consumerTag, boolean isRedelivered) - { - _deliveryTag = deliveryTag; - _routingKey = routingKey; - _exchangeName = exchangeName; - _consumerTag = consumerTag; - _isRedelivered = isRedelivered; - } - - public AMQBody createAMQBody() - { - return _methodRegistry.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(DataOutput buffer) throws IOException - { - 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!"); - } - - @Override - public String toString() - { - return "[" + getClass().getSimpleName() + " underlyingBody: " + String.valueOf(_underlyingBody) + "]"; - } - } - - private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) - throws AMQException - { - final AMQShortString exchangeName; - final AMQShortString routingKey; - - if(entry.getMessage() instanceof AMQMessage) - { - final AMQMessage message = (AMQMessage) entry.getMessage(); - final MessagePublishInfo pb = message.getMessagePublishInfo(); - exchangeName = pb.getExchange(); - routingKey = pb.getRoutingKey(); - } - else - { - MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); - exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); - routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); - } - - final boolean isRedelivered = entry.isRedelivered(); - - BasicGetOkBody getOkBody = - _methodRegistry.createBasicGetOkBody(deliveryTag, - isRedelivered, - exchangeName, - routingKey, - queueSize); - - return getOkBody; - } - - public byte getProtocolMinorVersion() - { - return _protocolSession.getProtocolMinorVersion(); - } - - public byte getProtocolMajorVersion() - { - return getProtocolSession().getProtocolMajorVersion(); - } - - private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, - int replyCode, - AMQShortString replyText) throws AMQException - { - - BasicReturnBody basicReturnBody = - _methodRegistry.createBasicReturnBody(replyCode, - replyText, - messagePublishInfo.getExchange(), - messagePublishInfo.getRoutingKey()); - - - return basicReturnBody; - } - - public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText) - throws AMQException - { - - AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText); - - writeMessageDelivery(message, header, channelId, returnFrame); - } - - - public void writeFrame(AMQDataBlock block) - { - getProtocolSession().writeFrame(block); - } - - - public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) - { - - BasicCancelOkBody basicCancelOkBody = _methodRegistry.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(DataOutput buffer) throws IOException - { - AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("[").append(getClass().getSimpleName()) - .append(" methodBody=").append(_methodBody) - .append(", headerBody=").append(_headerBody) - .append(", contentBody=").append(_contentBody) - .append(", channel=").append(_channel).append("]"); - return builder.toString(); - } - - } - - 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(DataOutput buffer) throws IOException - { - AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append(getClass().getSimpleName()) - .append("methodBody=").append(_methodBody) - .append(", headerBody=").append(_headerBody) - .append(", channel=").append(_channel).append("]"); - return builder.toString(); - } - } - -} \ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java deleted file mode 100644 index dcbfd89298..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java +++ /dev/null @@ -1,90 +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. - * - */ - -/* - * 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.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.server.output.ProtocolOutputConverter.Factory; -import org.apache.qpid.server.protocol.AMQProtocolSession; - -import java.util.HashMap; -import java.util.Map; - -public class ProtocolOutputConverterRegistry -{ - - private static final Map _registry = - new HashMap(); - - - static - { - register(ProtocolVersion.v8_0); - register(ProtocolVersion.v0_9); - register(ProtocolVersion.v0_91); - } - - private ProtocolOutputConverterRegistry() - { - } - - private static void register(ProtocolVersion version) - { - - _registry.put(version,new ConverterFactory(version)); - } - - - public static ProtocolOutputConverter getConverter(AMQProtocolSession session) - { - return _registry.get(session.getProtocolVersion()).newInstance(session); - } - - private static class ConverterFactory implements Factory - { - private ProtocolVersion _protocolVersion; - private MethodRegistry _methodRegistry; - private int _classId; - - public ConverterFactory(ProtocolVersion pv) - { - _protocolVersion = pv; - - } - - public synchronized ProtocolOutputConverter newInstance(AMQProtocolSession session) - { - if(_methodRegistry == null) - { - - _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); - - } - return new ProtocolOutputConverterImpl(session, _methodRegistry); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java deleted file mode 100644 index a7599a3e0d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java +++ /dev/null @@ -1,46 +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.framing.AMQMethodBody; -import org.apache.qpid.protocol.AMQMethodEvent; - -/** - * AMQNoMethodHandlerException represents the case where no method handler exists to handle an AQMP method. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Represents failure to handle an AMQP method. - *
- * - * @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 evt) - { - super("AMQMethodEvent " + evt + " was not processed by any listener on Broker."); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java deleted file mode 100644 index ef3fc97ab8..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ /dev/null @@ -1,1686 +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 java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import javax.security.auth.Subject; -import javax.security.sasl.SaslServer; - -import org.apache.log4j.Logger; -import org.apache.qpid.AMQChannelException; -import org.apache.qpid.AMQConnectionException; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.codec.AMQCodecFactory; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.framing.AMQBody; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQProtocolHeaderException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseBody; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.FieldTableFactory; -import org.apache.qpid.framing.HeartbeatBody; -import org.apache.qpid.framing.MethodDispatcher; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolInitiation; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.properties.ConnectionStartProperties; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.protocol.AMQMethodEvent; -import org.apache.qpid.protocol.AMQMethodListener; -import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.AMQPConnectionActor; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.stats.StatisticsCounter; -import org.apache.qpid.server.subscription.ClientDeliveryMethod; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionImpl; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.NetworkConnection; -import org.apache.qpid.util.BytesDataOutput; - -public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession -{ - private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); - - // to save boxing the channelId and looking up in a map... cache in an array the low numbered - // channels. This value must be of the form 2^x - 1. - private static final int CHANNEL_CACHE_SIZE = 0xff; - private static final int REUSABLE_BYTE_BUFFER_CAPACITY = 65 * 1024; - private final Port _port; - - private AMQShortString _contextKey; - - private String _clientVersion = null; - - private VirtualHost _virtualHost; - - private final Map _channelMap = new HashMap(); - - private final AMQChannel[] _cachedChannels = new AMQChannel[CHANNEL_CACHE_SIZE + 1]; - - /** - * The channels that the latest call to {@link #received(ByteBuffer)} applied to. - * Used so we know which channels we need to call {@link AMQChannel#receivedComplete()} - * on after handling the frames. - * - * Thread-safety: guarded by {@link #_receivedLock}. - */ - private final Set _channelsForCurrentMessage = new HashSet(); - - private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); - - private final AMQStateManager _stateManager; - - private AMQCodecFactory _codecFactory; - - private SaslServer _saslServer; - - private Object _lastReceived; - - private Object _lastSent; - - private volatile boolean _closed; - - // maximum number of channels this session should have - private long _maxNoOfChannels; - - /* AMQP Version for this session */ - private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion(); - private MethodRegistry _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); - private FieldTable _clientProperties; - private final List _taskList = new CopyOnWriteArrayList(); - - private Map _closingChannelsList = new ConcurrentHashMap(); - private ProtocolOutputConverter _protocolOutputConverter; - private Subject _authorizedSubject; - private MethodDispatcher _dispatcher; - - private final long _connectionID; - private Object _reference = new Object(); - - private AMQPConnectionActor _actor; - private LogSubject _logSubject; - - private long _lastIoTime; - - private long _writtenBytes; - private long _readBytes; - - - private long _maxFrameSize; - private final AtomicBoolean _closing = new AtomicBoolean(false); - private long _createTime = System.currentTimeMillis(); - - private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; - - private NetworkConnection _network; - private Sender _sender; - - private volatile boolean _deferFlush; - private long _lastReceivedTime; - private boolean _blocking; - - private final Lock _receivedLock; - private AtomicLong _lastWriteTime = new AtomicLong(System.currentTimeMillis()); - private final Broker _broker; - private final Transport _transport; - - private volatile boolean _closeWhenNoRoute; - private volatile boolean _stopped; - - public AMQProtocolEngine(Broker broker, - NetworkConnection network, - final long connectionId, - Port port, - Transport transport) - { - _broker = broker; - _port = port; - _transport = transport; - _maxNoOfChannels = (Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT); - _receivedLock = new ReentrantLock(); - _stateManager = new AMQStateManager(broker, this); - _codecFactory = new AMQCodecFactory(true, this); - - setNetworkConnection(network); - _connectionID = connectionId; - - _actor = new AMQPConnectionActor(this, _broker.getRootMessageLogger()); - - _logSubject = new ConnectionLogSubject(this); - - _actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false)); - - _closeWhenNoRoute = (Boolean)_broker.getAttribute(Broker.CONNECTION_CLOSE_WHEN_NO_ROUTE); - - initialiseStatistics(); - - } - - public void setNetworkConnection(NetworkConnection network) - { - setNetworkConnection(network, network.getSender()); - } - - public void setNetworkConnection(NetworkConnection network, Sender sender) - { - _network = network; - _sender = sender; - } - - public long getSessionID() - { - return _connectionID; - } - - public LogActor getLogActor() - { - return _actor; - } - - public void setMaxFrameSize(long frameMax) - { - _maxFrameSize = frameMax; - } - - public long getMaxFrameSize() - { - return _maxFrameSize; - } - - public boolean isClosing() - { - return _closing.get(); - } - - public synchronized void flushBatched() - { - _sender.flush(); - } - - - public ClientDeliveryMethod createDeliveryMethod(int channelId) - { - return new WriteDeliverMethod(channelId); - } - - public void received(final ByteBuffer msg) - { - final long arrivalTime = System.currentTimeMillis(); - _lastReceivedTime = arrivalTime; - _lastIoTime = arrivalTime; - - _receivedLock.lock(); - try - { - final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); - final int len = dataBlocks.size(); - for (int i = 0; i < len; i++) - { - AMQDataBlock dataBlock = dataBlocks.get(i); - try - { - dataBlockReceived(dataBlock); - } - catch(AMQConnectionException e) - { - if(_logger.isDebugEnabled()) - { - _logger.debug("Caught AMQConnectionException but will simply stop processing data blocks - the connection should already be closed.", e); - } - break; - } - catch (Exception e) - { - _logger.error("Unexpected exception when processing datablock", e); - closeProtocolSession(); - break; - } - } - receivedComplete(); - } - catch (Exception e) - { - _logger.error("Unexpected exception when processing datablocks", e); - closeProtocolSession(); - } - finally - { - _receivedLock.unlock(); - } - } - - private void receivedComplete() throws AMQException - { - Exception exception = null; - for (AMQChannel channel : _channelsForCurrentMessage) - { - try - { - channel.receivedComplete(); - } - catch(Exception exceptionForThisChannel) - { - if(exception == null) - { - exception = exceptionForThisChannel; - } - _logger.error("Error informing channel that receiving is complete. Channel: " + channel, exceptionForThisChannel); - } - } - - _channelsForCurrentMessage.clear(); - - if(exception != null) - { - throw new AMQException( - AMQConstant.INTERNAL_ERROR, - "Error informing channel that receiving is complete: " + exception.getMessage(), - exception); - } - } - - /** - * Process the data block. - * If the message is for a channel it is added to {@link #_channelsForCurrentMessage}. - * - * @throws an AMQConnectionException if unable to process the data block. In this case, - * the connection is already closed by the time the exception is thrown. If any other - * type of exception is thrown, the connection is not already closed. - */ - private void dataBlockReceived(AMQDataBlock message) throws Exception - { - _lastReceived = message; - if (message instanceof ProtocolInitiation) - { - protocolInitiationReceived((ProtocolInitiation) message); - - } - else if (message instanceof AMQFrame) - { - AMQFrame frame = (AMQFrame) message; - frameReceived(frame); - - } - else - { - throw new AMQException("Unknown message type: " + message.getClass().getName() + ": " + message); - } - } - - /** - * Handle the supplied frame. - * Adds this frame's channel to {@link #_channelsForCurrentMessage}. - * - * @throws an AMQConnectionException if unable to process the data block. In this case, - * the connection is already closed by the time the exception is thrown. If any other - * type of exception is thrown, the connection is not already closed. - */ - private void frameReceived(AMQFrame frame) throws AMQException - { - int channelId = frame.getChannel(); - AMQChannel amqChannel = _channelMap.get(channelId); - if(amqChannel != null) - { - // The _receivedLock is already aquired in the caller - // It is safe to add channel - _channelsForCurrentMessage.add(amqChannel); - } - else - { - // Not an error. The frame is probably a channel Open for this channel id, which - // does not require asynchronous work therefore its absence from - // _channelsForCurrentMessage is ok. - } - - AMQBody body = frame.getBodyFrame(); - - //Look up the Channel's Actor and set that as the current actor - // If that is not available then we can use the ConnectionActor - // that is associated with this AMQMPSession. - LogActor channelActor = null; - if (amqChannel != null) - { - channelActor = amqChannel.getLogActor(); - } - CurrentActor.set(channelActor == null ? _actor : channelActor); - - try - { - long startTime = 0; - String frameToString = null; - if (_logger.isDebugEnabled()) - { - startTime = System.currentTimeMillis(); - frameToString = frame.toString(); - _logger.debug("RECV: " + frame); - } - - // Check that this channel is not closing - if (channelAwaitingClosure(channelId)) - { - if ((frame.getBodyFrame() instanceof ChannelCloseOkBody)) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Channel[" + channelId + "] awaiting closure - processing close-ok"); - } - } - else - { - // The channel has been told to close, we don't process any more frames until - // it's closed. - return; - } - } - - try - { - body.handle(channelId, this); - } - catch(AMQConnectionException e) - { - _logger.info(e.getMessage() + " whilst processing frame: " + body); - closeConnection(channelId, e); - throw e; - } - catch (AMQException e) - { - closeChannel(channelId, e.getErrorCode() == null ? AMQConstant.INTERNAL_ERROR : e.getErrorCode(), e.getMessage()); - throw e; - } - catch (TransportException e) - { - closeChannel(channelId, AMQConstant.CHANNEL_ERROR, e.getMessage()); - throw e; - } - - if(_logger.isDebugEnabled()) - { - _logger.debug("Frame handled in " + (System.currentTimeMillis() - startTime) + " ms. Frame: " + frameToString); - } - } - finally - { - CurrentActor.remove(); - } - } - - private synchronized void protocolInitiationReceived(ProtocolInitiation pi) - { - // this ensures the codec never checks for a PI message again - (_codecFactory.getDecoder()).setExpectProtocolInitiation(false); - try - { - // Log incomming protocol negotiation request - _actor.message(ConnectionMessages.OPEN(null, pi.getProtocolMajor() + "-" + pi.getProtocolMinor(), null, false, true, false)); - - ProtocolVersion pv = pi.checkVersion(); // Fails if not correct - - // This sets the protocol version (and hence framing classes) for this session. - setProtocolVersion(pv); - - String mechanisms = _broker.getSubjectCreator(getLocalAddress()).getMechanisms(); - - String locales = "en_US"; - - - FieldTable serverProperties = FieldTableFactory.newFieldTable(); - - serverProperties.setString(ServerPropertyNames.PRODUCT, - QpidProperties.getProductName()); - serverProperties.setString(ServerPropertyNames.VERSION, - QpidProperties.getReleaseVersion()); - serverProperties.setString(ServerPropertyNames.QPID_BUILD, - QpidProperties.getBuildVersion()); - serverProperties.setString(ServerPropertyNames.QPID_INSTANCE_NAME, - _broker.getName()); - serverProperties.setString(ConnectionStartProperties.QPID_CLOSE_WHEN_NO_ROUTE, - String.valueOf(_closeWhenNoRoute)); - - AMQMethodBody responseBody = getMethodRegistry().createConnectionStartBody((short) getProtocolMajorVersion(), - (short) pv.getActualMinorVersion(), - serverProperties, - mechanisms.getBytes(), - locales.getBytes()); - _sender.send(asByteBuffer(responseBody.generateFrame(0))); - _sender.flush(); - - } - catch (AMQException e) - { - _logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion()); - - _sender.send(asByteBuffer(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()))); - _sender.flush(); - } - } - - - private final byte[] _reusableBytes = new byte[REUSABLE_BYTE_BUFFER_CAPACITY]; - private final ByteBuffer _reusableByteBuffer = ByteBuffer.wrap(_reusableBytes); - private final BytesDataOutput _reusableDataOutput = new BytesDataOutput(_reusableBytes); - - private ByteBuffer asByteBuffer(AMQDataBlock block) - { - final int size = (int) block.getSize(); - - final byte[] data; - - - if(size > REUSABLE_BYTE_BUFFER_CAPACITY) - { - data= new byte[size]; - } - else - { - - data = _reusableBytes; - } - _reusableDataOutput.setBuffer(data); - - try - { - block.writePayload(_reusableDataOutput); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - - final ByteBuffer buf; - - if(size <= REUSABLE_BYTE_BUFFER_CAPACITY) - { - buf = _reusableByteBuffer; - buf.position(0); - } - else - { - buf = ByteBuffer.wrap(data); - } - buf.limit(_reusableDataOutput.length()); - - return buf; - } - - public void methodFrameReceived(int channelId, AMQMethodBody methodBody) - { - final AMQMethodEvent evt = new AMQMethodEvent(channelId, methodBody); - - try - { - try - { - boolean wasAnyoneInterested = _stateManager.methodReceived(evt); - - if (!_frameListeners.isEmpty()) - { - for (AMQMethodListener listener : _frameListeners) - { - wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested; - } - } - - if (!wasAnyoneInterested) - { - throw new AMQNoMethodHandlerException(evt); - } - } - catch (AMQChannelException e) - { - if (getChannel(channelId) != null) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Closing channel due to: " + e.getMessage()); - } - - writeFrame(e.getCloseFrame(channelId)); - closeChannel(channelId, e.getErrorCode() == null ? AMQConstant.INTERNAL_ERROR : e.getErrorCode(), e.getMessage()); - } - else - { - if (_logger.isDebugEnabled()) - { - _logger.debug("ChannelException occured on non-existent channel:" + e.getMessage()); - } - - if (_logger.isInfoEnabled()) - { - _logger.info("Closing connection due to: " + e.getMessage()); - } - - AMQConnectionException ce = - evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR, - AMQConstant.CHANNEL_ERROR.getName().toString()); - - _logger.info(e.getMessage() + " whilst processing:" + methodBody); - closeConnection(channelId, ce); - } - } - catch (AMQConnectionException e) - { - _logger.info(e.getMessage() + " whilst processing:" + methodBody); - closeConnection(channelId, e); - } - catch (AMQSecurityException e) - { - AMQConnectionException ce = evt.getMethod().getConnectionException(AMQConstant.ACCESS_REFUSED, e.getMessage()); - _logger.info(e.getMessage() + " whilst processing:" + methodBody); - closeConnection(channelId, ce); - } - } - catch (Exception e) - { - for (AMQMethodListener listener : _frameListeners) - { - listener.error(e); - } - - _logger.error("Unexpected exception while processing frame. Closing connection.", e); - - closeProtocolSession(); - } - } - - public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException - { - - AMQChannel channel = getAndAssertChannel(channelId); - - channel.publishContentHeader(body); - - } - - public void contentBodyReceived(int channelId, ContentBody body) throws AMQException - { - AMQChannel channel = getAndAssertChannel(channelId); - - channel.publishContentBody(body); - } - - public void heartbeatBodyReceived(int channelId, HeartbeatBody body) - { - // NO - OP - } - - /** - * Convenience method that writes a frame to the protocol session. Equivalent to calling - * getProtocolSession().write(). - * - * @param frame the frame to write - */ - public synchronized void writeFrame(AMQDataBlock frame) - { - - final ByteBuffer buf = asByteBuffer(frame); - _writtenBytes += buf.remaining(); - - if(_logger.isDebugEnabled()) - { - _logger.debug("SEND: " + frame); - } - - _sender.send(buf); - final long time = System.currentTimeMillis(); - _lastIoTime = time; - _lastWriteTime.set(time); - - if(!_deferFlush) - { - _sender.flush(); - } - } - - public AMQShortString getContextKey() - { - return _contextKey; - } - - public void setContextKey(AMQShortString contextKey) - { - _contextKey = contextKey; - } - - public List getChannels() - { - synchronized (_channelMap) - { - return new ArrayList(_channelMap.values()); - } - } - - public AMQChannel getAndAssertChannel(int channelId) throws AMQException - { - AMQChannel channel = getChannel(channelId); - if (channel == null) - { - throw new AMQException(AMQConstant.NOT_FOUND, "Channel not found with id:" + channelId); - } - - return channel; - } - - public AMQChannel getChannel(int channelId) - { - final AMQChannel channel = - ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId); - if ((channel == null) || channel.isClosing()) - { - return null; - } - else - { - return channel; - } - } - - public boolean channelAwaitingClosure(int channelId) - { - return !_closingChannelsList.isEmpty() && _closingChannelsList.containsKey(channelId); - } - - public void addChannel(AMQChannel channel) throws AMQException - { - if (_closed) - { - throw new AMQException("Session is closed"); - } - - final int channelId = channel.getChannelId(); - - if (_closingChannelsList.containsKey(channelId)) - { - throw new AMQException("Session is marked awaiting channel close"); - } - - if (_channelMap.size() == _maxNoOfChannels) - { - String errorMessage = - toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels - + "); can't create channel"; - _logger.error(errorMessage); - throw new AMQException(AMQConstant.NOT_ALLOWED, errorMessage); - } - else - { - synchronized (_channelMap) - { - _channelMap.put(channel.getChannelId(), channel); - - if(_blocking) - { - channel.block(); - } - } - } - - if (((channelId & CHANNEL_CACHE_SIZE) == channelId)) - { - _cachedChannels[channelId] = channel; - } - } - - public Long getMaximumNumberOfChannels() - { - return _maxNoOfChannels; - } - - public void setMaximumNumberOfChannels(Long value) - { - _maxNoOfChannels = value; - } - - public void commitTransactions(AMQChannel channel) throws AMQException - { - if ((channel != null) && channel.isTransactional()) - { - channel.commit(); - } - } - - public void rollbackTransactions(AMQChannel channel) throws AMQException - { - if ((channel != null) && channel.isTransactional()) - { - channel.rollback(); - } - } - - /** - * Close a specific channel. This will remove any resources used by the channel, including:

  • any queue - * subscriptions (this may in turn remove queues if they are auto delete
- * - * @param channelId id of the channel to close - * - * @throws AMQException if an error occurs closing the channel - * @throws IllegalArgumentException if the channel id is not valid - */ - @Override - public void closeChannel(int channelId) throws AMQException - { - closeChannel(channelId, null, null); - } - - public void closeChannel(int channelId, AMQConstant cause, String message) throws AMQException - { - final AMQChannel channel = getChannel(channelId); - if (channel == null) - { - throw new IllegalArgumentException("Unknown channel id"); - } - else - { - try - { - channel.close(cause, message); - markChannelAwaitingCloseOk(channelId); - } - finally - { - removeChannel(channelId); - } - } - } - - public void closeChannelOk(int channelId) - { - // todo QPID-847 - This is called from two lcoations ChannelCloseHandler and ChannelCloseOkHandler. - // When it is the CC_OK_Handler then it makes sence to remove the channel else we will leak memory. - // We do it from the Close Handler as we are sending the OK back to the client. - // While this is AMQP spec compliant. The Java client in the event of an IllegalArgumentException - // will send a close-ok.. Where we should call removeChannel. - // However, due to the poor exception handling on the client. The client-user will be notified of the - // InvalidArgument and if they then decide to close the session/connection then the there will be time - // for that to occur i.e. a new close method be sent before the exeption handling can mark the session closed. - - _closingChannelsList.remove(channelId); - } - - private void markChannelAwaitingCloseOk(int channelId) - { - _closingChannelsList.put(channelId, System.currentTimeMillis()); - } - - /** - * In our current implementation this is used by the clustering code. - * - * @param channelId The channel to remove - */ - public void removeChannel(int channelId) - { - synchronized (_channelMap) - { - _channelMap.remove(channelId); - - if ((channelId & CHANNEL_CACHE_SIZE) == channelId) - { - _cachedChannels[channelId] = null; - } - } - } - - /** - * Initialise heartbeats on the session. - * - * @param delay delay in seconds (not ms) - */ - public void initHeartbeats(int delay) - { - if (delay > 0) - { - _network.setMaxWriteIdle(delay); - _network.setMaxReadIdle(BrokerProperties.HEARTBEAT_TIMEOUT_FACTOR * delay); - } - else - { - _network.setMaxWriteIdle(0); - _network.setMaxReadIdle(0); - } - } - - /** - * Closes all channels that were opened by this protocol session. This frees up all resources used by the channel. - * - * @throws AMQException if an error occurs while closing any channel - */ - private void closeAllChannels() throws AMQException - { - for (AMQChannel channel : getChannels()) - { - channel.close(); - } - synchronized (_channelMap) - { - _channelMap.clear(); - } - for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++) - { - _cachedChannels[i] = null; - } - } - - /** This must be called when the session is _closed in order to free up any resources managed by the session. */ - @Override - public void closeSession() throws AMQException - { - if(_closing.compareAndSet(false,true)) - { - // force sync of outstanding async work - _receivedLock.lock(); - try - { - receivedComplete(); - } - finally - { - _receivedLock.unlock(); - } - - // REMOVE THIS SHOULD NOT BE HERE. - if (CurrentActor.get() == null) - { - CurrentActor.set(_actor); - } - if (!_closed) - { - if (_virtualHost != null) - { - _virtualHost.getConnectionRegistry().deregisterConnection(this); - } - - closeAllChannels(); - - for (Task task : _taskList) - { - task.doTask(this); - } - - synchronized(this) - { - _closed = true; - notifyAll(); - } - CurrentActor.get().message(_logSubject, ConnectionMessages.CLOSE()); - } - } - else - { - synchronized(this) - { - while(!_closed) - { - try - { - wait(1000); - } - catch (InterruptedException e) - { - - } - } - } - } - } - - private void closeConnection(int channelId, AMQConnectionException e) throws AMQException - { - try - { - if (_logger.isInfoEnabled()) - { - _logger.info("Closing connection due to: " + e); - } - - markChannelAwaitingCloseOk(channelId); - closeSession(); - } - finally - { - try - { - _stateManager.changeState(AMQState.CONNECTION_CLOSING); - writeFrame(e.getCloseFrame(channelId)); - } - finally - { - closeProtocolSession(); - } - } - - - } - - @Override - public void closeProtocolSession() - { - _network.close(); - - try - { - _stateManager.changeState(AMQState.CONNECTION_CLOSED); - } - catch (AMQException e) - { - _logger.info(e.getMessage()); - } - catch (TransportException e) - { - _logger.info(e.getMessage()); - } - } - - public String toString() - { - return getRemoteAddress() + "(" + (getAuthorizedPrincipal() == null ? "?" : getAuthorizedPrincipal().getName() + ")"); - } - - public String dump() - { - return this + " last_sent=" + _lastSent + " last_received=" + _lastReceived; - } - - /** @return an object that can be used to identity */ - public Object getKey() - { - return getRemoteAddress(); - } - - /** - * Get the fully qualified domain name of the local address to which this session is bound. Since some servers may - * be bound to multiple addresses this could vary depending on the acceptor this session was created from. - * - * @return a String FQDN - */ - public String getLocalFQDN() - { - SocketAddress address = _network.getLocalAddress(); - if (address instanceof InetSocketAddress) - { - return ((InetSocketAddress) address).getHostName(); - } - else - { - throw new IllegalArgumentException("Unsupported socket address class: " + address); - } - } - - public SaslServer getSaslServer() - { - return _saslServer; - } - - public void setSaslServer(SaslServer saslServer) - { - _saslServer = saslServer; - } - - public void setClientProperties(FieldTable clientProperties) - { - _clientProperties = clientProperties; - if (_clientProperties != null) - { - String closeWhenNoRoute = _clientProperties.getString(ConnectionStartProperties.QPID_CLOSE_WHEN_NO_ROUTE); - if (closeWhenNoRoute != null) - { - _closeWhenNoRoute = Boolean.parseBoolean(closeWhenNoRoute); - if(_logger.isDebugEnabled()) - { - _logger.debug("Client set closeWhenNoRoute=" + _closeWhenNoRoute + " for protocol engine " + this); - } - } - - _clientVersion = _clientProperties.getString(ConnectionStartProperties.VERSION_0_8); - - if (_clientProperties.getString(ConnectionStartProperties.CLIENT_ID_0_8) != null) - { - String clientID = _clientProperties.getString(ConnectionStartProperties.CLIENT_ID_0_8); - setContextKey(new AMQShortString(clientID)); - - // Log the Opening of the connection for this client - _actor.message(ConnectionMessages.OPEN(clientID, _protocolVersion.toString(), _clientVersion, true, true, true)); - } - } - } - - private void setProtocolVersion(ProtocolVersion pv) - { - _protocolVersion = pv; - _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); - _protocolOutputConverter = ProtocolOutputConverterRegistry.getConverter(this); - _dispatcher = ServerMethodDispatcherImpl.createMethodDispatcher(_stateManager, _protocolVersion); - } - - public byte getProtocolMajorVersion() - { - return _protocolVersion.getMajorVersion(); - } - - public ProtocolVersion getProtocolVersion() - { - return _protocolVersion; - } - - public byte getProtocolMinorVersion() - { - return _protocolVersion.getMinorVersion(); - } - - public boolean isProtocolVersion(byte major, byte minor) - { - return (getProtocolMajorVersion() == major) && (getProtocolMinorVersion() == minor); - } - - public MethodRegistry getRegistry() - { - return getMethodRegistry(); - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public void setVirtualHost(VirtualHost virtualHost) throws AMQException - { - _virtualHost = virtualHost; - - _virtualHost.getConnectionRegistry().registerConnection(this); - - } - - public void addSessionCloseTask(Task task) - { - _taskList.add(task); - } - - public void removeSessionCloseTask(Task task) - { - _taskList.remove(task); - } - - public ProtocolOutputConverter getProtocolOutputConverter() - { - return _protocolOutputConverter; - } - - public void setAuthorizedSubject(final Subject authorizedSubject) - { - if (authorizedSubject == null) - { - throw new IllegalArgumentException("authorizedSubject cannot be null"); - } - _authorizedSubject = authorizedSubject; - } - - public Subject getAuthorizedSubject() - { - return _authorizedSubject; - } - - public Principal getAuthorizedPrincipal() - { - return _authorizedSubject == null ? null : AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(_authorizedSubject); - } - - public SocketAddress getRemoteAddress() - { - return _network.getRemoteAddress(); - } - - public SocketAddress getLocalAddress() - { - return _network.getLocalAddress(); - } - - public Principal getPeerPrincipal() - { - return _network.getPeerPrincipal(); - } - - public MethodRegistry getMethodRegistry() - { - return _methodRegistry; - } - - public MethodDispatcher getMethodDispatcher() - { - return _dispatcher; - } - - public void closed() - { - try - { - try - { - closeSession(); - } - finally - { - closeProtocolSession(); - } - } - catch (AMQException e) - { - _logger.error("Could not close protocol engine", e); - } - catch (TransportException e) - { - _logger.error("Could not close protocol engine", e); - } - } - - public void readerIdle() - { - // TODO - enforce disconnect on lack of inbound data - } - - public synchronized void writerIdle() - { - writeFrame(HeartbeatBody.FRAME); - } - - public void exception(Throwable throwable) - { - if (throwable instanceof AMQProtocolHeaderException) - { - writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())); - _sender.close(); - - _logger.error("Error in protocol initiation " + this + ":" + getRemoteAddress() + " :" + throwable.getMessage(), throwable); - } - else if (throwable instanceof IOException) - { - _logger.error("IOException caught in" + this + ", session closed implictly: " + throwable); - } - else - { - _logger.error("Exception caught in" + this + ", closing session explictly: " + throwable, throwable); - - - MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion()); - ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0); - - writeFrame(closeBody.generateFrame(0)); - - _sender.close(); - } - } - - public void init() - { - // Do nothing - } - - public void setSender(Sender sender) - { - // Do nothing - } - - public long getReadBytes() - { - return _readBytes; - } - - public long getWrittenBytes() - { - return _writtenBytes; - } - - public long getLastIoTime() - { - return _lastIoTime; - } - - @Override - public Port getPort() - { - return _port; - } - - @Override - public Transport getTransport() - { - return _transport; - } - - @Override - public void stop() - { - _stopped = true; - } - - @Override - public boolean isStopped() - { - return _stopped; - } - - public long getLastReceivedTime() - { - return _lastReceivedTime; - } - - public String getClientVersion() - { - return _clientVersion; - } - - public String getPrincipalAsString() - { - return getAuthId(); - } - - public long getSessionCountLimit() - { - return getMaximumNumberOfChannels(); - } - - public Boolean isIncoming() - { - return true; - } - - public Boolean isSystemConnection() - { - return false; - } - - public Boolean isFederationLink() - { - return false; - } - - public String getAuthId() - { - return getAuthorizedPrincipal().getName(); - } - - public Integer getRemotePID() - { - return null; - } - - public String getRemoteProcessName() - { - return null; - } - - public Integer getRemoteParentPID() - { - return null; - } - - public boolean isDurable() - { - return false; - } - - public long getConnectionId() - { - return getSessionID(); - } - - public String getAddress() - { - return String.valueOf(getRemoteAddress()); - } - - public long getCreateTime() - { - return _createTime; - } - - public Boolean isShadow() - { - return false; - } - - public void mgmtClose() - { - MethodRegistry methodRegistry = getMethodRegistry(); - ConnectionCloseBody responseBody = - methodRegistry.createConnectionCloseBody( - AMQConstant.REPLY_SUCCESS.getCode(), - new AMQShortString("The connection was closed using the broker's management interface."), - 0,0); - - // This seems ugly but because we use closeConnection in both normal - // broker operation and as part of the management interface it cannot - // be avoided. The Current Actor will be null when this method is - // called via the QMF management interface. As such we need to set one. - boolean removeActor = false; - if (CurrentActor.get() == null) - { - removeActor = true; - CurrentActor.set(new ManagementActor(_actor.getRootMessageLogger())); - } - - try - { - writeFrame(responseBody.generateFrame(0)); - - try - { - - closeSession(); - } - catch (AMQException ex) - { - throw new RuntimeException(ex); - } - } - finally - { - if (removeActor) - { - CurrentActor.remove(); - } - } - } - - public void mgmtCloseChannel(int channelId) - { - MethodRegistry methodRegistry = getMethodRegistry(); - ChannelCloseBody responseBody = - methodRegistry.createChannelCloseBody( - AMQConstant.REPLY_SUCCESS.getCode(), - new AMQShortString("The channel was closed using the broker's management interface."), - 0,0); - - // This seems ugly but because we use AMQChannel.close() in both normal - // broker operation and as part of the management interface it cannot - // be avoided. The Current Actor will be null when this method is - // called via the QMF management interface. As such we need to set one. - boolean removeActor = false; - if (CurrentActor.get() == null) - { - removeActor = true; - CurrentActor.set(new ManagementActor(_actor.getRootMessageLogger())); - } - - try - { - writeFrame(responseBody.generateFrame(channelId)); - - try - { - closeChannel(channelId); - } - catch (AMQException ex) - { - throw new RuntimeException(ex); - } - } - finally - { - if (removeActor) - { - CurrentActor.remove(); - } - } - } - - public String getClientID() - { - return getContextKey().toString(); - } - - public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException - { - int channelId = ((AMQChannel)session).getChannelId(); - closeChannel(channelId, cause, message); - - MethodRegistry methodRegistry = getMethodRegistry(); - ChannelCloseBody responseBody = - methodRegistry.createChannelCloseBody( - cause.getCode(), - new AMQShortString(message), - 0,0); - - writeFrame(responseBody.generateFrame(channelId)); - } - - public void close(AMQConstant cause, String message) throws AMQException - { - closeConnection(0, new AMQConnectionException(cause, message, 0, 0, - getProtocolOutputConverter().getProtocolMajorVersion(), - getProtocolOutputConverter().getProtocolMinorVersion(), - (Throwable) null)); - } - - public void block() - { - synchronized (_channelMap) - { - if(!_blocking) - { - _blocking = true; - for(AMQChannel channel : _channelMap.values()) - { - channel.block(); - } - } - } - } - - public void unblock() - { - synchronized (_channelMap) - { - if(_blocking) - { - _blocking = false; - for(AMQChannel channel : _channelMap.values()) - { - channel.unblock(); - } - } - } - } - - public boolean isClosed() - { - return _closed; - } - - public List getSessionModels() - { - return new ArrayList(getChannels()); - } - - public LogSubject getLogSubject() - { - return _logSubject; - } - - public void registerMessageDelivered(long messageSize) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - _virtualHost.registerMessageDelivered(messageSize); - } - - public void registerMessageReceived(long messageSize, long timestamp) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - _virtualHost.registerMessageReceived(messageSize, timestamp); - } - - public StatisticsCounter getMessageReceiptStatistics() - { - return _messagesReceived; - } - - public StatisticsCounter getDataReceiptStatistics() - { - return _dataReceived; - } - - public StatisticsCounter getMessageDeliveryStatistics() - { - return _messagesDelivered; - } - - public StatisticsCounter getDataDeliveryStatistics() - { - return _dataDelivered; - } - - public void resetStatistics() - { - _messagesDelivered.reset(); - _dataDelivered.reset(); - _messagesReceived.reset(); - _dataReceived.reset(); - } - - public void initialiseStatistics() - { - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getSessionID()); - _dataDelivered = new StatisticsCounter("data-delivered-" + getSessionID()); - _messagesReceived = new StatisticsCounter("messages-received-" + getSessionID()); - _dataReceived = new StatisticsCounter("data-received-" + getSessionID()); - } - - public boolean isSessionNameUnique(byte[] name) - { - // 0-8/0-9/0-9-1 sessions don't have names - return true; - } - - public String getRemoteAddressString() - { - return String.valueOf(getRemoteAddress()); - } - - public String getClientId() - { - return String.valueOf(getContextKey()); - } - - public void setDeferFlush(boolean deferFlush) - { - _deferFlush = deferFlush; - } - - public String getUserName() - { - return getAuthorizedPrincipal().getName(); - } - - public final class WriteDeliverMethod - implements ClientDeliveryMethod - { - private final int _channelId; - - public WriteDeliverMethod(int channelId) - { - _channelId = channelId; - } - - public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) - throws AMQException - { - registerMessageDelivered(entry.getMessage().getSize()); - _protocolOutputConverter.writeDeliver(entry, _channelId, deliveryTag, ((SubscriptionImpl)sub).getConsumerTag()); - entry.incrementDeliveryCount(); - } - - } - - public Object getReference() - { - return _reference; - } - - public Lock getReceivedLock() - { - return _receivedLock; - } - - @Override - public long getLastReadTime() - { - return _lastReceivedTime; - } - - @Override - public long getLastWriteTime() - { - return _lastWriteTime.get(); - } - - @Override - public boolean isCloseWhenNoRoute() - { - return _closeWhenNoRoute; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java index 6fa497c853..5ed7017e46 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java @@ -35,9 +35,9 @@ import org.apache.qpid.framing.MethodDispatcher; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 3834d22180..5e920f1c4e 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -37,7 +37,12 @@ import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.transport.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ProtocolEngine_0_10; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ServerConnectionDelegate; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolEngine; +import org.apache.qpid.server.protocol.v1_0.ProtocolEngine_1_0_0; +import org.apache.qpid.server.protocol.v1_0.ProtocolEngine_1_0_0_SASL; import org.apache.qpid.transport.ConnectionDelegate; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; @@ -325,7 +330,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - final ConnectionDelegate connDelegate = new org.apache.qpid.server.transport.ServerConnectionDelegate(_broker, + final ConnectionDelegate connDelegate = new ServerConnectionDelegate(_broker, _fqdn, _broker.getSubjectCreator(getLocalAddress())); ServerConnection conn = new ServerConnection(_id); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java deleted file mode 100755 index 8275ab690c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java +++ /dev/null @@ -1,198 +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.protocol.ServerProtocolEngine; -import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.network.Assembler; -import org.apache.qpid.transport.network.Disassembler; -import org.apache.qpid.transport.network.InputHandler; -import org.apache.qpid.transport.network.NetworkConnection; - -import java.net.SocketAddress; -import java.nio.ByteBuffer; - - -public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine -{ - public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; - - private NetworkConnection _network; - private long _readBytes; - private long _writtenBytes; - private ServerConnection _connection; - - private long _createTime = System.currentTimeMillis(); - private long _lastReadTime; - private long _lastWriteTime; - - public ProtocolEngine_0_10(ServerConnection conn, - NetworkConnection network, Port port, Transport transport) - { - super(new Assembler(conn)); - _connection = conn; - _connection.setPort(port); - _connection.setTransport(transport); - - if(network != null) - { - setNetworkConnection(network); - } - - - } - - public void setNetworkConnection(NetworkConnection network) - { - setNetworkConnection(network, network.getSender()); - } - - public void setNetworkConnection(NetworkConnection network, Sender sender) - { - _network = network; - - _connection.setNetworkConnection(network); - _connection.setSender(new Disassembler(wrapSender(sender), MAX_FRAME_SIZE)); - _connection.setPeerPrincipal(_network.getPeerPrincipal()); - // FIXME Two log messages to maintain compatibility with earlier protocol versions - _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false)); - _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false)); - } - - private Sender wrapSender(final Sender sender) - { - return new Sender() - { - @Override - public void setIdleTimeout(int i) - { - sender.setIdleTimeout(i); - - } - - @Override - public void send(ByteBuffer msg) - { - _lastWriteTime = System.currentTimeMillis(); - sender.send(msg); - - } - - @Override - public void flush() - { - sender.flush(); - - } - - @Override - public void close() - { - sender.close(); - - } - }; - } - - @Override - public long getLastReadTime() - { - return _lastReadTime; - } - - @Override - public long getLastWriteTime() - { - return _lastWriteTime; - } - - public SocketAddress getRemoteAddress() - { - return _network.getRemoteAddress(); - } - - public SocketAddress getLocalAddress() - { - return _network.getLocalAddress(); - } - - public void received(final ByteBuffer buf) - { - _lastReadTime = System.currentTimeMillis(); - super.received(buf); - _connection.receivedComplete(); - } - - public long getReadBytes() - { - return _readBytes; - } - - public long getWrittenBytes() - { - return _writtenBytes; - } - - public void writerIdle() - { - _connection.doHeartbeat(); - } - - public void readerIdle() - { - //Todo - } - - public String getAddress() - { - return getRemoteAddress().toString(); - } - - public String getAuthId() - { - return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName(); - } - - public boolean isDurable() - { - return false; - } - - @Override - public void closed() - { - super.closed(); - } - - public long getCreateTime() - { - return _createTime; - } - - public long getConnectionId() - { - return _connection.getConnectionId(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java deleted file mode 100755 index 7d5459dce6..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java +++ /dev/null @@ -1,427 +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 java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import org.apache.qpid.amqp_1_0.codec.FrameWriter; -import org.apache.qpid.amqp_1_0.framing.AMQFrame; -import org.apache.qpid.amqp_1_0.framing.FrameHandler; -import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; -import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; -import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; -import org.apache.qpid.amqp_1_0.transport.Container; -import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.qpid.amqp_1_0.type.FrameBody; -import org.apache.qpid.amqp_1_0.type.Symbol; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.protocol.v1_0.Connection_1_0; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.UsernamePrincipal; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.network.NetworkConnection; - -public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHandler -{ - static final AtomicLong _connectionIdSource = new AtomicLong(0L); - private final Port _port; - private final Transport _transport; - - //private NetworkConnection _networkDriver; - private long _readBytes; - private long _writtenBytes; - private long _lastReadTime; - private long _lastWriteTime; - private final Broker _broker; - private long _createTime = System.currentTimeMillis(); - private ConnectionEndpoint _conn; - private final long _connectionId; - - private static final ByteBuffer HEADER = - ByteBuffer.wrap(new byte[] - { - (byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte) 0, - (byte) 1, - (byte) 0, - (byte) 0 - }); - - private FrameWriter _frameWriter; - private FrameHandler _frameHandler; - private Object _sendLock = new Object(); - private byte _major; - private byte _minor; - private byte _revision; - private NetworkConnection _network; - private Sender _sender; - - - static enum State { - A, - M, - Q, - P, - PROTOCOL, - MAJOR, - MINOR, - REVISION, - FRAME - } - - private State _state = State.A; - - - - public ProtocolEngine_1_0_0(final NetworkConnection networkDriver, - final Broker broker, - long id, - Port port, - Transport transport) - { - _broker = broker; - _port = port; - _transport = transport; - _connectionId = id; - if(networkDriver != null) - { - setNetworkConnection(networkDriver, networkDriver.getSender()); - } - } - - - public SocketAddress getRemoteAddress() - { - return _network.getRemoteAddress(); - } - - public SocketAddress getLocalAddress() - { - return _network.getLocalAddress(); - } - - public long getReadBytes() - { - return _readBytes; - } - - public long getWrittenBytes() - { - return _writtenBytes; - } - - public void writerIdle() - { - //Todo - } - - public void readerIdle() - { - //Todo - } - - public void setNetworkConnection(final NetworkConnection network, final Sender sender) - { - _network = network; - _sender = sender; - - Container container = new Container(_broker.getId().toString()); - - VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); - - _conn = new ConnectionEndpoint(container, asSaslServerProvider(_broker.getSubjectCreator( - getLocalAddress()))); - - Map serverProperties = new LinkedHashMap(); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.PRODUCT), QpidProperties.getProductName()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.VERSION), QpidProperties.getReleaseVersion()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_BUILD), QpidProperties.getBuildVersion()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_INSTANCE_NAME), _broker.getName()); - - _conn.setProperties(serverProperties); - - _conn.setRemoteAddress(_network.getRemoteAddress()); - _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId, _port, _transport)); - _conn.setFrameOutputHandler(this); - - _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry()); - _frameHandler = new FrameHandler(_conn); - - _sender.send(HEADER.duplicate()); - _sender.flush(); - } - - private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) - { - return new SaslServerProvider() - { - @Override - public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException - { - return subjectCreator.createSaslServer(mechanism, fqdn, null); - } - - @Override - public Principal getAuthenticatedPrincipal(SaslServer server) - { - return new UsernamePrincipal(server.getAuthorizationID()); - } - }; - } - - public String getAddress() - { - return getRemoteAddress().toString(); - } - - public boolean isDurable() - { - return false; - } - - public synchronized void received(ByteBuffer msg) - { - _lastReadTime = System.currentTimeMillis(); - if(RAW_LOGGER.isLoggable(Level.FINE)) - { - ByteBuffer dup = msg.duplicate(); - byte[] data = new byte[dup.remaining()]; - dup.get(data); - Binary bin = new Binary(data); - RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString()); - } - _readBytes += msg.remaining(); - switch(_state) - { - case A: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - break; - } - case M: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.M; - break; - } - - case Q: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.Q; - break; - } - case P: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.P; - break; - } - case PROTOCOL: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.PROTOCOL; - break; - } - case MAJOR: - if(msg.hasRemaining()) - { - _major = msg.get(); - } - else - { - _state = State.MAJOR; - break; - } - case MINOR: - if(msg.hasRemaining()) - { - _minor = msg.get(); - } - else - { - _state = State.MINOR; - break; - } - case REVISION: - if(msg.hasRemaining()) - { - _revision = msg.get(); - - _state = State.FRAME; - } - else - { - _state = State.REVISION; - break; - } - case FRAME: - if(msg.hasRemaining()) - { - _frameHandler.parse(msg); - } - } - - } - - public void exception(Throwable t) - { - t.printStackTrace(); - } - - public void closed() - { - _conn.inputClosed(); - if(_conn != null && _conn.getConnectionEventListener() != null) - { - ((Connection_1_0)_conn.getConnectionEventListener()).closed(); - } - - } - - public long getCreateTime() - { - return _createTime; - } - - - public boolean canSend() - { - return true; - } - - public void send(final AMQFrame amqFrame) - { - send(amqFrame, null); - } - - private final Logger FRAME_LOGGER = Logger.getLogger("FRM"); - private final Logger RAW_LOGGER = Logger.getLogger("RAW"); - - - public void send(final AMQFrame amqFrame, ByteBuffer buf) - { - synchronized(_sendLock) - { - - _lastWriteTime = System.currentTimeMillis(); - if(FRAME_LOGGER.isLoggable(Level.FINE)) - { - FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); - } - - - _frameWriter.setValue(amqFrame); - - - - ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize()); - - int size = _frameWriter.writeToBuffer(dup); - if(size > _conn.getMaxFrameSize()) - { - throw new OversizeFrameException(amqFrame,size); - } - - dup.flip(); - _writtenBytes += dup.limit(); - - if(RAW_LOGGER.isLoggable(Level.FINE)) - { - ByteBuffer dup2 = dup.duplicate(); - byte[] data = new byte[dup2.remaining()]; - dup2.get(data); - Binary bin = new Binary(data); - RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString()); - } - - - _sender.send(dup); - _sender.flush(); - - } - } - - public void send(short channel, FrameBody body) - { - AMQFrame frame = AMQFrame.createAMQFrame(channel, body); - send(frame); - - } - - public void close() - { - //TODO - } - - public long getConnectionId() - { - return _connectionId; - } - - public long getLastReadTime() - { - return _lastReadTime; - } - - public long getLastWriteTime() - { - return _lastWriteTime; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java deleted file mode 100644 index 9472e08ca5..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java +++ /dev/null @@ -1,462 +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 java.io.PrintWriter; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import org.apache.qpid.amqp_1_0.codec.FrameWriter; -import org.apache.qpid.amqp_1_0.codec.ProtocolHandler; -import org.apache.qpid.amqp_1_0.framing.AMQFrame; -import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; -import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler; -import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; -import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; -import org.apache.qpid.amqp_1_0.transport.Container; -import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.qpid.amqp_1_0.type.FrameBody; -import org.apache.qpid.amqp_1_0.type.Symbol; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.protocol.v1_0.Connection_1_0; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.UsernamePrincipal; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Sender; -import org.apache.qpid.transport.network.NetworkConnection; - -public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOutputHandler -{ - private final Port _port; - private final Transport _transport; - private long _readBytes; - private long _writtenBytes; - - private long _lastReadTime; - private long _lastWriteTime; - private final Broker _broker; - private long _createTime = System.currentTimeMillis(); - private ConnectionEndpoint _conn; - private long _connectionId; - - private static final ByteBuffer HEADER = - ByteBuffer.wrap(new byte[] - { - (byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte) 3, - (byte) 1, - (byte) 0, - (byte) 0 - }); - - private static final ByteBuffer PROTOCOL_HEADER = - ByteBuffer.wrap(new byte[] - { - (byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte) 0, - (byte) 1, - (byte) 0, - (byte) 0 - }); - - - private FrameWriter _frameWriter; - private ProtocolHandler _frameHandler; - private ByteBuffer _buf = ByteBuffer.allocate(1024 * 1024); - private Object _sendLock = new Object(); - private byte _major; - private byte _minor; - private byte _revision; - private PrintWriter _out; - private NetworkConnection _network; - private Sender _sender; - - - static enum State { - A, - M, - Q, - P, - PROTOCOL, - MAJOR, - MINOR, - REVISION, - FRAME - } - - private State _state = State.A; - - - public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final Broker broker, - long id, Port port, Transport transport) - { - _connectionId = id; - _broker = broker; - _port = port; - _transport = transport; - if(networkDriver != null) - { - setNetworkConnection(networkDriver, networkDriver.getSender()); - } - } - - - public SocketAddress getRemoteAddress() - { - return _network.getRemoteAddress(); - } - - public SocketAddress getLocalAddress() - { - return _network.getLocalAddress(); - } - - public long getReadBytes() - { - return _readBytes; - } - - public long getWrittenBytes() - { - return _writtenBytes; - } - - public void writerIdle() - { - //Todo - } - - public void readerIdle() - { - //Todo - } - - public void setNetworkConnection(final NetworkConnection network, final Sender sender) - { - _network = network; - _sender = sender; - - Container container = new Container(_broker.getId().toString()); - - VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); - SubjectCreator subjectCreator = _broker.getSubjectCreator(getLocalAddress()); - _conn = new ConnectionEndpoint(container, asSaslServerProvider(subjectCreator)); - - Map serverProperties = new LinkedHashMap(); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.PRODUCT), QpidProperties.getProductName()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.VERSION), QpidProperties.getReleaseVersion()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_BUILD), QpidProperties.getBuildVersion()); - serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_INSTANCE_NAME), _broker.getName()); - - _conn.setProperties(serverProperties); - - _conn.setRemoteAddress(getRemoteAddress()); - _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId, _port, _transport)); - _conn.setFrameOutputHandler(this); - _conn.setSaslFrameOutput(this); - - _conn.setOnSaslComplete(new Runnable() - { - public void run() - { - if(_conn.isAuthenticated()) - { - _sender.send(PROTOCOL_HEADER.duplicate()); - _sender.flush(); - } - else - { - _network.close(); - } - } - }); - _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry()); - _frameHandler = new SASLFrameHandler(_conn); - - _sender.send(HEADER.duplicate()); - _sender.flush(); - - _conn.initiateSASL(subjectCreator.getMechanisms().split(" ")); - - - } - - private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) - { - return new SaslServerProvider() - { - @Override - public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException - { - return subjectCreator.createSaslServer(mechanism, fqdn, _network.getPeerPrincipal()); - } - - @Override - public Principal getAuthenticatedPrincipal(SaslServer server) - { - return new UsernamePrincipal(server.getAuthorizationID()); - } - }; - } - - public String getAddress() - { - return getRemoteAddress().toString(); - } - - public boolean isDurable() - { - return false; - } - - private final Logger RAW_LOGGER = Logger.getLogger("RAW"); - - - public synchronized void received(ByteBuffer msg) - { - _lastReadTime = System.currentTimeMillis(); - if(RAW_LOGGER.isLoggable(Level.FINE)) - { - ByteBuffer dup = msg.duplicate(); - byte[] data = new byte[dup.remaining()]; - dup.get(data); - Binary bin = new Binary(data); - RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString()); - } - _readBytes += msg.remaining(); - switch(_state) - { - case A: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - break; - } - case M: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.M; - break; - } - - case Q: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.Q; - break; - } - case P: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.P; - break; - } - case PROTOCOL: - if(msg.hasRemaining()) - { - msg.get(); - } - else - { - _state = State.PROTOCOL; - break; - } - case MAJOR: - if(msg.hasRemaining()) - { - _major = msg.get(); - } - else - { - _state = State.MAJOR; - break; - } - case MINOR: - if(msg.hasRemaining()) - { - _minor = msg.get(); - } - else - { - _state = State.MINOR; - break; - } - case REVISION: - if(msg.hasRemaining()) - { - _revision = msg.get(); - - _state = State.FRAME; - } - else - { - _state = State.REVISION; - break; - } - case FRAME: - if(msg.hasRemaining()) - { - _frameHandler = _frameHandler.parse(msg); - } - } - - } - - public void exception(Throwable t) - { - t.printStackTrace(); - } - - public void closed() - { - // todo - _conn.inputClosed(); - if (_conn != null && _conn.getConnectionEventListener() != null) - { - ((Connection_1_0) _conn.getConnectionEventListener()).closed(); - } - - } - - public long getCreateTime() - { - return _createTime; - } - - - public boolean canSend() - { - return true; - } - - public void send(final AMQFrame amqFrame) - { - send(amqFrame, null); - } - - private static final Logger FRAME_LOGGER = Logger.getLogger("FRM"); - - - public void send(final AMQFrame amqFrame, ByteBuffer buf) - { - - synchronized (_sendLock) - { - _lastWriteTime = System.currentTimeMillis(); - if (FRAME_LOGGER.isLoggable(Level.FINE)) - { - FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); - } - - _frameWriter.setValue(amqFrame); - - ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize()); - - int size = _frameWriter.writeToBuffer(dup); - if (size > _conn.getMaxFrameSize()) - { - throw new OversizeFrameException(amqFrame, size); - } - - dup.flip(); - _writtenBytes += dup.limit(); - - if (RAW_LOGGER.isLoggable(Level.FINE)) - { - ByteBuffer dup2 = dup.duplicate(); - byte[] data = new byte[dup2.remaining()]; - dup2.get(data); - Binary bin = new Binary(data); - RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString()); - } - - _sender.send(dup); - _sender.flush(); - - - } - } - - public void send(short channel, FrameBody body) - { - AMQFrame frame = AMQFrame.createAMQFrame(channel, body); - send(frame); - - } - - public void close() - { - _sender.close(); - } - - public void setLogOutput(final PrintWriter out) - { - _out = out; - } - - public long getConnectionId() - { - return _connectionId; - } - - public long getLastReadTime() - { - return _lastReadTime; - } - - public long getLastWriteTime() - { - return _lastWriteTime; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java new file mode 100644 index 0000000000..cee1a04b17 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.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.protocol.v0_10; + + +import org.apache.qpid.server.flow.AbstractFlowCreditManager;public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 +{ + private volatile long _bytesCredit; + private volatile long _messageCredit; + + public CreditCreditManager(long bytesCredit, long messageCredit) + { + _bytesCredit = bytesCredit; + _messageCredit = messageCredit; + setSuspended(!hasCredit()); + + } + + + public synchronized void setCreditLimits(final long bytesCredit, final long messageCredit) + { + _bytesCredit = bytesCredit; + _messageCredit = messageCredit; + + setSuspended(!hasCredit()); + + } + + + public long getMessageCredit() + { + return _messageCredit == -1L + ? Long.MAX_VALUE + : _messageCredit; + } + + public long getBytesCredit() + { + return _bytesCredit == -1L + ? Long.MAX_VALUE + : _bytesCredit; + } + + public synchronized void restoreCredit(final long messageCredit, final long bytesCredit) + { + } + + + public synchronized void addCredit(final long messageCredit, final long bytesCredit) + { + boolean notifyIncrease = true; + if(_messageCredit >= 0L && messageCredit > 0L) + { + notifyIncrease = _messageCredit != 0L; + _messageCredit += messageCredit; + } + + + + if(_bytesCredit >= 0L && bytesCredit > 0L) + { + notifyIncrease = notifyIncrease && bytesCredit>0; + _bytesCredit += bytesCredit; + + + + if(notifyIncrease) + { + notifyIncreaseBytesCredit(); + } + } + + + + setSuspended(!hasCredit()); + + } + + public void clearCredit() + { + _bytesCredit = 0l; + _messageCredit = 0l; + setSuspended(true); + } + + + public synchronized boolean hasCredit() + { + // Note !=, if credit is < 0 that indicates infinite credit + return (_bytesCredit != 0L && _messageCredit != 0L); + } + + public synchronized boolean useCreditForMessage(long msgSize) + { + if(_messageCredit >= 0L) + { + if(_messageCredit > 0) + { + if(_bytesCredit < 0L) + { + _messageCredit--; + + return true; + } + else if(msgSize <= _bytesCredit) + { + _messageCredit--; + _bytesCredit -= msgSize; + + return true; + } + else + { + return false; + } + } + else + { + setSuspended(true); + return false; + } + } + else if(_bytesCredit >= 0L) + { + if(msgSize <= _bytesCredit) + { + _bytesCredit -= msgSize; + + return true; + } + else + { + return false; + } + + } + else + { + return true; + } + + } + + public synchronized void stop() + { + if(_bytesCredit > 0) + { + _bytesCredit = 0; + } + if(_messageCredit > 0) + { + _messageCredit = 0; + } + + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java new file mode 100755 index 0000000000..4b38b8a1a3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java @@ -0,0 +1,93 @@ +/* + * + * 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.v0_10; + +import org.apache.log4j.Logger; + +import org.apache.qpid.server.queue.QueueEntry; + + +class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener +{ + private static final Logger _logger = Logger.getLogger(ExplicitAcceptDispositionChangeListener.class); + + + private final QueueEntry _entry; + private final Subscription_0_10 _sub; + + public ExplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) + { + _entry = entry; + _sub = subscription_0_10; + } + + public void onAccept() + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.getSessionModel().acknowledge(subscription, _entry); + } + else + { + _logger.warn("MessageAccept received for message which has not been acquired (likely client error)"); + } + + } + + public void onRelease(boolean setRedelivered) + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.release(_entry, setRedelivered); + } + else + { + _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); + } + } + + public void onReject() + { + final Subscription_0_10 subscription = getSubscription(); + if(subscription != null && _entry.isAcquiredBy(_sub)) + { + subscription.reject(_entry); + } + else + { + _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); + } + + } + + public boolean acquire() + { + return _entry.acquire(getSubscription()); + } + + + private Subscription_0_10 getSubscription() + { + return _sub; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.java new file mode 100755 index 0000000000..7f092814da --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.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.protocol.v0_10; + +import org.apache.qpid.server.flow.FlowCreditManager; + +public interface FlowCreditManager_0_10 extends FlowCreditManager +{ + public void addCredit(long count, long bytes); + + void clearCredit(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java new file mode 100755 index 0000000000..ce0155b789 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java @@ -0,0 +1,88 @@ +/* + * + * 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.v0_10; + +import org.apache.log4j.Logger; + +import org.apache.qpid.server.queue.QueueEntry; + +class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener +{ + private static final Logger _logger = Logger.getLogger(ImplicitAcceptDispositionChangeListener.class); + + + private final QueueEntry _entry; + private Subscription_0_10 _sub; + + public ImplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) + { + _entry = entry; + _sub = subscription_0_10; + } + + public void onAccept() + { + _logger.warn("MessageAccept received for message which is using NONE as the accept mode (likely client error)"); + } + + public void onRelease(boolean setRedelivered) + { + if(_entry.isAcquiredBy(_sub)) + { + getSubscription().release(_entry, setRedelivered); + } + else + { + _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); + } + } + + public void onReject() + { + if(_entry.isAcquiredBy(_sub)) + { + getSubscription().reject(_entry); + } + else + { + _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); + } + + } + + public boolean acquire() + { + boolean acquired = _entry.acquire(getSubscription()); + if(acquired) + { + getSubscription().recordUnacknowledged(_entry); + } + return acquired; + + } + + public Subscription_0_10 getSubscription() + { + return _sub; + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java new file mode 100755 index 0000000000..f5f2a8d43f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java @@ -0,0 +1,56 @@ +/* + * + * 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.v0_10; + +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.transport.Method; + +public class MessageAcceptCompletionListener implements Method.CompletionListener +{ + private final Subscription_0_10 _sub; + private final QueueEntry _entry; + private final ServerSession _session; + private boolean _restoreCredit; + + public MessageAcceptCompletionListener(Subscription_0_10 sub, ServerSession session, QueueEntry entry, boolean restoreCredit) + { + super(); + _sub = sub; + _entry = entry; + _session = session; + _restoreCredit = restoreCredit; + } + + public void onComplete(Method method) + { + if(_restoreCredit) + { + _sub.restoreCredit(_entry); + } + if(_entry.isAcquiredBy(_sub)) + { + _session.acknowledge(_sub, _entry); + } + + _session.removeDispositionListener(method); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java new file mode 100755 index 0000000000..2d17351dad --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java @@ -0,0 +1,279 @@ +/* +* +* 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.v0_10; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Struct; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.codec.BBEncoder; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMessage +{ + private Header _header; + private DeliveryProperties _deliveryProps; + private MessageProperties _messageProps; + private MessageTransferHeader _messageHeader; + private long _arrivalTime; + private int _bodySize; + + private static final int ENCODER_SIZE = 1 << 10; + + public static final MessageMetaDataType.Factory FACTORY = new MetaDataFactory(); + + private volatile ByteBuffer _encoded; + private Object _connectionReference; + + + public MessageMetaData_0_10(MessageTransfer xfr) + { + this(xfr.getHeader(), xfr.getBodySize(), System.currentTimeMillis()); + } + + private MessageMetaData_0_10(Header header, int bodySize, long arrivalTime) + { + _header = header; + if(_header != null) + { + _deliveryProps = _header.getDeliveryProperties(); + _messageProps = _header.getMessageProperties(); + } + else + { + _deliveryProps = null; + _messageProps = null; + } + _messageHeader = new MessageTransferHeader(_deliveryProps, _messageProps); + _arrivalTime = arrivalTime; + _bodySize = bodySize; + + } + + + + public MessageMetaDataType getType() + { + return MessageMetaDataType.META_DATA_0_10; + } + + public int getStorableSize() + { + ByteBuffer buf = _encoded; + + if(buf == null) + { + buf = encodeAsBuffer(); + _encoded = buf; + } + + //TODO -- need to add stuff + return buf.limit(); + } + + private ByteBuffer encodeAsBuffer() + { + BBEncoder encoder = new BBEncoder(ENCODER_SIZE); + + encoder.writeInt64(_arrivalTime); + encoder.writeInt32(_bodySize); + int headersLength = 0; + if(_header.getDeliveryProperties() != null) + { + headersLength++; + } + if(_header.getMessageProperties() != null) + { + headersLength++; + } + if(_header.getNonStandardProperties() != null) + { + headersLength += _header.getNonStandardProperties().size(); + } + + encoder.writeInt32(headersLength); + + if(_header.getDeliveryProperties() != null) + { + encoder.writeStruct32(_header.getDeliveryProperties()); + } + if(_header.getMessageProperties() != null) + { + encoder.writeStruct32(_header.getMessageProperties()); + } + if(_header.getNonStandardProperties() != null) + { + + for(Struct header : _header.getNonStandardProperties()) + { + encoder.writeStruct32(header); + } + + } + ByteBuffer buf = encoder.buffer(); + return buf; + } + + public int writeToBuffer(int offsetInMetaData, ByteBuffer dest) + { + ByteBuffer buf = _encoded; + + if(buf == null) + { + buf = encodeAsBuffer(); + _encoded = buf; + } + + buf = buf.duplicate(); + + buf.position(offsetInMetaData); + + if(dest.remaining() < buf.limit()) + { + buf.limit(dest.remaining()); + } + dest.put(buf); + return buf.limit(); + } + + public int getContentSize() + { + return _bodySize; + } + + public boolean isPersistent() + { + return _deliveryProps == null ? false : _deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT; + } + + public String getRoutingKey() + { + return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); + } + + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(getRoutingKey()); + } + + public AMQMessageHeader getMessageHeader() + { + return _messageHeader; + } + + public long getSize() + { + + return _bodySize; + } + + public boolean isImmediate() + { + return _deliveryProps != null && _deliveryProps.getImmediate(); + } + + public long getExpiration() + { + return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); + } + + public boolean isRedelivered() + { + // The *Message* is never redelivered, only queue entries are... + return false; + } + + public long getArrivalTime() + { + return _arrivalTime; + } + + public Header getHeader() + { + return _header; + } + + public void setConnectionReference(Object connectionReference) + { + _connectionReference = connectionReference; + } + + public Object getConnectionReference() + { + return _connectionReference; + } + + private static class MetaDataFactory implements MessageMetaDataType.Factory + { + public MessageMetaData_0_10 createMetaData(ByteBuffer buf) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(buf); + + long arrivalTime = decoder.readInt64(); + int bodySize = decoder.readInt32(); + int headerCount = decoder.readInt32(); + + DeliveryProperties deliveryProperties = null; + MessageProperties messageProperties = null; + List otherProps = null; + + for(int i = 0 ; i < headerCount; i++) + { + Struct struct = decoder.readStruct32(); + if(struct instanceof DeliveryProperties && deliveryProperties == null) + { + deliveryProperties = (DeliveryProperties) struct; + } + else if(struct instanceof MessageProperties && messageProperties == null) + { + messageProperties = (MessageProperties) struct; + } + else + { + if(otherProps == null) + { + otherProps = new ArrayList(); + + } + otherProps.add(struct); + } + } + Header header = new Header(deliveryProperties,messageProperties,otherProps); + + return new MessageMetaData_0_10(header, bodySize, arrivalTime); + + } + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.java new file mode 100644 index 0000000000..1b506d9bf8 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.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.server.protocol.v0_10; + +import java.util.*; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageProperties; + +class MessageTransferHeader implements AMQMessageHeader +{ + + + public static final String JMS_TYPE = "x-jms-type"; + + private final DeliveryProperties _deliveryProps; + private final MessageProperties _messageProps; + + public MessageTransferHeader(DeliveryProperties deliveryProps, MessageProperties messageProps) + { + _deliveryProps = deliveryProps; + _messageProps = messageProps; + } + + public String getCorrelationId() + { + if (_messageProps != null && _messageProps.getCorrelationId() != null) + { + return new String(_messageProps.getCorrelationId()); + } + else + { + return null; + } + } + + public long getExpiration() + { + return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); + } + + public String getUserId() + { + byte[] userIdBytes = _messageProps == null ? null : _messageProps.getUserId(); + return userIdBytes == null ? null : new String(userIdBytes); + } + + public String getAppId() + { + byte[] appIdBytes = _messageProps == null ? null : _messageProps.getAppId(); + return appIdBytes == null ? null : new String(appIdBytes); + } + + public String getMessageId() + { + UUID id = _messageProps == null ? null : _messageProps.getMessageId(); + + return id == null ? null : String.valueOf(id); + } + + public String getMimeType() + { + return _messageProps == null ? null : _messageProps.getContentType(); + } + + public String getEncoding() + { + return _messageProps == null ? null : _messageProps.getContentEncoding(); + } + + public byte getPriority() + { + MessageDeliveryPriority priority = _deliveryProps == null || !_deliveryProps.hasPriority() + ? MessageDeliveryPriority.MEDIUM + : _deliveryProps.getPriority(); + return (byte) priority.getValue(); + } + + public long getTimestamp() + { + return _deliveryProps == null ? 0L : _deliveryProps.getTimestamp(); + } + + public String getType() + { + Object type = getHeader(JMS_TYPE); + return type instanceof String ? (String) type : null; + } + + public String getReplyTo() + { + if (_messageProps != null && _messageProps.getReplyTo() != null) + { + return _messageProps.getReplyTo().toString(); + } + else + { + return null; + } + } + + public String getReplyToExchange() + { + if (_messageProps != null && _messageProps.getReplyTo() != null) + { + return _messageProps.getReplyTo().getExchange(); + } + else + { + return null; + } + } + + public String getReplyToRoutingKey() + { + if (_messageProps != null && _messageProps.getReplyTo() != null) + { + return _messageProps.getReplyTo().getRoutingKey(); + } + else + { + return null; + } + } + + public Object getHeader(String name) + { + Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); + return appHeaders == null ? null : appHeaders.get(name); + } + + public boolean containsHeaders(Set names) + { + Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); + return appHeaders != null && appHeaders.keySet().containsAll(names); + + } + + @Override + public Collection getHeaderNames() + { + Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); + return appHeaders != null ? Collections.unmodifiableCollection(appHeaders.keySet()) : Collections.EMPTY_SET ; + + } + + public boolean containsHeader(String name) + { + Map appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); + return appHeaders != null && appHeaders.containsKey(name); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java new file mode 100644 index 0000000000..4e8bfcb652 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java @@ -0,0 +1,136 @@ +/* + * + * 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.v0_10; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AbstractServerMessageImpl; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.transport.Header; + +import java.nio.ByteBuffer; + + +public class MessageTransferMessage extends AbstractServerMessageImpl implements InboundMessage +{ + + private Object _connectionRef; + + public MessageTransferMessage(StoredMessage storeMessage, Object connectionRef) + { + super(storeMessage); + _connectionRef = connectionRef; + } + + private MessageMetaData_0_10 getMetaData() + { + return getStoredMessage().getMetaData(); + } + + public String getRoutingKey() + { + return getMetaData().getRoutingKey(); + } + + public AMQShortString getRoutingKeyShortString() + { + return AMQShortString.valueOf(getRoutingKey()); + } + + public AMQMessageHeader getMessageHeader() + { + return getMetaData().getMessageHeader(); + } + + public boolean isPersistent() + { + return getMetaData().isPersistent(); + } + + + public boolean isRedelivered() + { + // The *Message* is never redelivered, only queue entries are... this is here so that filters + // can run against the message on entry to an exchange + return false; + } + + public long getSize() + { + + return getMetaData().getSize(); + } + + public boolean isImmediate() + { + return getMetaData().isImmediate(); + } + + public long getExpiration() + { + return getMetaData().getExpiration(); + } + + public MessageReference newReference() + { + return new TransferMessageReference(this); + } + + public long getMessageNumber() + { + return getStoredMessage().getMessageNumber(); + } + + public long getArrivalTime() + { + return getMetaData().getArrivalTime(); + } + + public int getContent(ByteBuffer buf, int offset) + { + return getStoredMessage().getContent(offset, buf); + } + + + public ByteBuffer getContent(int offset, int size) + { + return getStoredMessage().getContent(offset,size); + } + + public Header getHeader() + { + return getMetaData().getHeader(); + } + + public ByteBuffer getBody() + { + + return getContent(0, (int)getSize()); + } + + public Object getConnectionReference() + { + return _connectionRef; + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java new file mode 100755 index 0000000000..d1919c30e2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java @@ -0,0 +1,198 @@ +/* + * + * 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.v0_10; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.logging.messages.ConnectionMessages; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.transport.network.InputHandler; +import org.apache.qpid.transport.network.NetworkConnection; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; + + +public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine +{ + public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; + + private NetworkConnection _network; + private long _readBytes; + private long _writtenBytes; + private ServerConnection _connection; + + private long _createTime = System.currentTimeMillis(); + private long _lastReadTime; + private long _lastWriteTime; + + public ProtocolEngine_0_10(ServerConnection conn, + NetworkConnection network, Port port, Transport transport) + { + super(new Assembler(conn)); + _connection = conn; + _connection.setPort(port); + _connection.setTransport(transport); + + if(network != null) + { + setNetworkConnection(network); + } + + + } + + public void setNetworkConnection(NetworkConnection network) + { + setNetworkConnection(network, network.getSender()); + } + + public void setNetworkConnection(NetworkConnection network, Sender sender) + { + _network = network; + + _connection.setNetworkConnection(network); + _connection.setSender(new Disassembler(wrapSender(sender), MAX_FRAME_SIZE)); + _connection.setPeerPrincipal(_network.getPeerPrincipal()); + // FIXME Two log messages to maintain compatibility with earlier protocol versions + _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false)); + _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false)); + } + + private Sender wrapSender(final Sender sender) + { + return new Sender() + { + @Override + public void setIdleTimeout(int i) + { + sender.setIdleTimeout(i); + + } + + @Override + public void send(ByteBuffer msg) + { + _lastWriteTime = System.currentTimeMillis(); + sender.send(msg); + + } + + @Override + public void flush() + { + sender.flush(); + + } + + @Override + public void close() + { + sender.close(); + + } + }; + } + + @Override + public long getLastReadTime() + { + return _lastReadTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime; + } + + public SocketAddress getRemoteAddress() + { + return _network.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _network.getLocalAddress(); + } + + public void received(final ByteBuffer buf) + { + _lastReadTime = System.currentTimeMillis(); + super.received(buf); + _connection.receivedComplete(); + } + + public long getReadBytes() + { + return _readBytes; + } + + public long getWrittenBytes() + { + return _writtenBytes; + } + + public void writerIdle() + { + _connection.doHeartbeat(); + } + + public void readerIdle() + { + //Todo + } + + public String getAddress() + { + return getRemoteAddress().toString(); + } + + public String getAuthId() + { + return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName(); + } + + public boolean isDurable() + { + return false; + } + + @Override + public void closed() + { + super.closed(); + } + + public long getCreateTime() + { + return _createTime; + } + + public long getConnectionId() + { + return _connection.getConnectionId(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java new file mode 100644 index 0000000000..1b0f068646 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java @@ -0,0 +1,551 @@ +/* + * + * 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.v0_10; + +import java.net.SocketAddress; +import java.security.Principal; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import javax.security.auth.Subject; +import org.apache.qpid.AMQException; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.logging.messages.ConnectionMessages; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.security.AuthorizationHolder; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.stats.StatisticsCounter; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionCloseCode; +import org.apache.qpid.transport.ExecutionErrorCode; +import org.apache.qpid.transport.ExecutionException; +import org.apache.qpid.transport.Method; +import org.apache.qpid.transport.ProtocolEvent; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.network.NetworkConnection; + +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT; +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT; +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT; + +public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder +{ + private Runnable _onOpenTask; + private AtomicBoolean _logClosed = new AtomicBoolean(false); + private LogActor _actor = GenericActor.getInstance(this); + + private Subject _authorizedSubject = null; + private Principal _authorizedPrincipal = null; + private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; + private final long _connectionId; + private final Object _reference = new Object(); + private VirtualHost _virtualHost; + private Port _port; + private AtomicLong _lastIoTime = new AtomicLong(); + private boolean _blocking; + private Principal _peerPrincipal; + private NetworkConnection _networkConnection; + private Transport _transport; + private volatile boolean _stopped; + + public ServerConnection(final long connectionId) + { + _connectionId = connectionId; + } + + public Object getReference() + { + return _reference; + } + + @Override + protected void invoke(Method method) + { + super.invoke(method); + } + + @Override + protected void setState(State state) + { + super.setState(state); + + if (state == State.OPEN) + { + if (_onOpenTask != null) + { + _onOpenTask.run(); + } + _actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", getClientVersion(), true, true, true)); + + getVirtualHost().getConnectionRegistry().registerConnection(this); + } + + if (state == State.CLOSE_RCVD || state == State.CLOSED || state == State.CLOSING) + { + if(_virtualHost != null) + { + _virtualHost.getConnectionRegistry().deregisterConnection(this); + } + } + + if (state == State.CLOSED) + { + logClosed(); + } + } + + protected void logClosed() + { + if(_logClosed.compareAndSet(false, true)) + { + CurrentActor.get().message(this, ConnectionMessages.CLOSE()); + } + } + + @Override + public ServerConnectionDelegate getConnectionDelegate() + { + return (ServerConnectionDelegate) super.getConnectionDelegate(); + } + + public void setConnectionDelegate(ServerConnectionDelegate delegate) + { + super.setConnectionDelegate(delegate); + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public void setVirtualHost(VirtualHost virtualHost) + { + _virtualHost = virtualHost; + + initialiseStatistics(); + } + + @Override + public Port getPort() + { + return _port; + } + + public void setPort(Port port) + { + _port = port; + } + + @Override + public Transport getTransport() + { + return _transport; + } + + @Override + public void stop() + { + _stopped = true; + } + + @Override + public boolean isStopped() + { + return _stopped; + } + + public void setTransport(Transport transport) + { + _transport = transport; + } + + public void onOpen(final Runnable task) + { + _onOpenTask = task; + } + + public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException + { + ExecutionException ex = new ExecutionException(); + ExecutionErrorCode code = ExecutionErrorCode.INTERNAL_ERROR; + try + { + code = ExecutionErrorCode.get(cause.getCode()); + } + catch (IllegalArgumentException iae) + { + // Ignore, already set to INTERNAL_ERROR + } + ex.setErrorCode(code); + ex.setDescription(message); + ((ServerSession)session).invoke(ex); + + ((ServerSession)session).close(cause, message); + } + + public LogSubject getLogSubject() + { + return (LogSubject) this; + } + + @Override + public void received(ProtocolEvent event) + { + _lastIoTime.set(System.currentTimeMillis()); + if (event.isConnectionControl()) + { + CurrentActor.set(_actor); + } + else + { + ServerSession channel = (ServerSession) getSession(event.getChannel()); + LogActor channelActor = null; + + if (channel != null) + { + channelActor = channel.getLogActor(); + } + + CurrentActor.set(channelActor == null ? _actor : channelActor); + } + + try + { + super.received(event); + } + finally + { + CurrentActor.remove(); + } + } + + public String toLogString() + { + boolean hasVirtualHost = (null != this.getVirtualHost()); + boolean hasClientId = (null != getClientId()); + + if (hasClientId && hasVirtualHost) + { + return "[" + + MessageFormat.format(CONNECTION_FORMAT, + getConnectionId(), + getClientId(), + getRemoteAddressString(), + getVirtualHost().getName()) + + "] "; + } + else if (hasClientId) + { + return "[" + + MessageFormat.format(USER_FORMAT, + getConnectionId(), + getClientId(), + getRemoteAddressString()) + + "] "; + + } + else + { + return "[" + + MessageFormat.format(SOCKET_FORMAT, + getConnectionId(), + getRemoteAddressString()) + + "] "; + } + } + + public LogActor getLogActor() + { + return _actor; + } + + public void close(AMQConstant cause, String message) throws AMQException + { + closeSubscriptions(); + ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL; + try + { + replyCode = ConnectionCloseCode.get(cause.getCode()); + } + catch (IllegalArgumentException iae) + { + // Ignore + } + close(replyCode, message); + } + + public synchronized void block() + { + if(!_blocking) + { + _blocking = true; + for(AMQSessionModel ssn : getSessionModels()) + { + ssn.block(); + } + } + } + + public synchronized void unblock() + { + if(_blocking) + { + _blocking = false; + for(AMQSessionModel ssn : getSessionModels()) + { + ssn.unblock(); + } + } + } + + @Override + public synchronized void registerSession(final Session ssn) + { + super.registerSession(ssn); + if(_blocking) + { + ((ServerSession)ssn).block(); + } + } + + @Override + public synchronized void removeSession(final Session ssn) + { + super.removeSession(ssn); + } + + public List getSessionModels() + { + List sessions = new ArrayList(); + for (Session ssn : getChannels()) + { + sessions.add((AMQSessionModel) ssn); + } + return sessions; + } + + public void registerMessageDelivered(long messageSize) + { + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); + _virtualHost.registerMessageDelivered(messageSize); + } + + public void registerMessageReceived(long messageSize, long timestamp) + { + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); + _virtualHost.registerMessageReceived(messageSize, timestamp); + } + + public StatisticsCounter getMessageReceiptStatistics() + { + return _messagesReceived; + } + + public StatisticsCounter getDataReceiptStatistics() + { + return _dataReceived; + } + + public StatisticsCounter getMessageDeliveryStatistics() + { + return _messagesDelivered; + } + + public StatisticsCounter getDataDeliveryStatistics() + { + return _dataDelivered; + } + + public void resetStatistics() + { + _messagesDelivered.reset(); + _dataDelivered.reset(); + _messagesReceived.reset(); + _dataReceived.reset(); + } + + public void initialiseStatistics() + { + _messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId()); + _dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId()); + _messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId()); + _dataReceived = new StatisticsCounter("data-received-" + getConnectionId()); + } + + /** + * @return authorizedSubject + */ + public Subject getAuthorizedSubject() + { + return _authorizedSubject; + } + + /** + * Sets the authorized subject. It also extracts the UsernamePrincipal from the subject + * and caches it for optimisation purposes. + * + * @param authorizedSubject + */ + public void setAuthorizedSubject(final Subject authorizedSubject) + { + if (authorizedSubject == null) + { + _authorizedSubject = null; + _authorizedPrincipal = null; + } + else + { + _authorizedSubject = authorizedSubject; + _authorizedPrincipal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(authorizedSubject); + } + } + + public Principal getAuthorizedPrincipal() + { + return _authorizedPrincipal; + } + + public long getConnectionId() + { + return _connectionId; + } + + public boolean isSessionNameUnique(byte[] name) + { + return !super.hasSessionWithName(name); + } + + public String getRemoteAddressString() + { + return String.valueOf(getRemoteAddress()); + } + + public String getUserName() + { + return _authorizedPrincipal.getName(); + } + + @Override + public void closed() + { + closeSubscriptions(); + super.closed(); + } + + private void closeSubscriptions() + { + for (Session ssn : getChannels()) + { + ((ServerSession)ssn).unregisterSubscriptions(); + } + } + + public void receivedComplete() + { + for (Session ssn : getChannels()) + { + ((ServerSession)ssn).receivedComplete(); + } + } + + @Override + public void send(ProtocolEvent event) + { + _lastIoTime.set(System.currentTimeMillis()); + super.send(event); + } + + public long getLastIoTime() + { + return _lastIoTime.longValue(); + } + + + public String getClientId() + { + return getConnectionDelegate().getClientId(); + } + + public String getClientVersion() + { + return getConnectionDelegate().getClientVersion(); + } + + public String getPrincipalAsString() + { + return getAuthorizedPrincipal().getName(); + } + + public long getSessionCountLimit() + { + return getChannelMax(); + } + + public Principal getPeerPrincipal() + { + return _peerPrincipal; + } + + public void setPeerPrincipal(Principal peerPrincipal) + { + _peerPrincipal = peerPrincipal; + } + + @Override + public void setRemoteAddress(SocketAddress remoteAddress) + { + super.setRemoteAddress(remoteAddress); + } + + @Override + public void setLocalAddress(SocketAddress localAddress) + { + super.setLocalAddress(localAddress); + } + + public void setNetworkConnection(NetworkConnection network) + { + _networkConnection = network; + } + + public NetworkConnection getNetworkConnection() + { + return _networkConnection; + } + + public void doHeartbeat() + { + super.doHeartBeat(); + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java new file mode 100644 index 0000000000..6634627805 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java @@ -0,0 +1,350 @@ +/* + * + * 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.v0_10; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.common.ServerPropertyNames; +import org.apache.qpid.properties.ConnectionStartProperties; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.virtualhost.State; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.NetworkConnection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD; + +public class ServerConnectionDelegate extends ServerDelegate +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ServerConnectionDelegate.class); + + private final Broker _broker; + private final String _localFQDN; + private int _maxNoOfChannels; + private Map _clientProperties; + private final SubjectCreator _subjectCreator; + + public ServerConnectionDelegate(Broker broker, String localFQDN, SubjectCreator subjectCreator) + { + this(createConnectionProperties(broker), Collections.singletonList((Object)"en_US"), broker, localFQDN, subjectCreator); + } + + private ServerConnectionDelegate(Map properties, + List locales, + Broker broker, + String localFQDN, + SubjectCreator subjectCreator) + { + super(properties, parseToList(subjectCreator.getMechanisms()), locales); + + _broker = broker; + _localFQDN = localFQDN; + _maxNoOfChannels = (Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT); + _subjectCreator = subjectCreator; + } + + private static List getFeatures(Broker broker) + { + String brokerDisabledFeatures = System.getProperty(BrokerProperties.PROPERTY_DISABLED_FEATURES); + final List features = new ArrayList(); + if (brokerDisabledFeatures == null || !brokerDisabledFeatures.contains(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR)) + { + features.add(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR); + } + + return Collections.unmodifiableList(features); + } + + private static Map createConnectionProperties(final Broker broker) + { + final Map map = new HashMap(); + // Federation tag is used by the client to identify the broker instance + map.put(ServerPropertyNames.FEDERATION_TAG, broker.getId().toString()); + final List features = getFeatures(broker); + if (features != null && features.size() > 0) + { + map.put(ServerPropertyNames.QPID_FEATURES, features); + } + + map.put(ServerPropertyNames.PRODUCT, QpidProperties.getProductName()); + map.put(ServerPropertyNames.VERSION, QpidProperties.getReleaseVersion()); + map.put(ServerPropertyNames.QPID_BUILD, QpidProperties.getBuildVersion()); + map.put(ServerPropertyNames.QPID_INSTANCE_NAME, broker.getName()); + + return map; + } + + private static List parseToList(String mechanisms) + { + List list = new ArrayList(); + StringTokenizer tokenizer = new StringTokenizer(mechanisms, " "); + while(tokenizer.hasMoreTokens()) + { + list.add(tokenizer.nextToken()); + } + return list; + } + + public ServerSession getSession(Connection conn, SessionAttach atc) + { + SessionDelegate serverSessionDelegate = new ServerSessionDelegate(); + + ServerSession ssn = new ServerSession(conn, serverSessionDelegate, new Binary(atc.getName()), 0); + + return ssn; + } + + protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException + { + return _subjectCreator.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal()); + + } + + protected void secure(final SaslServer ss, final Connection conn, final byte[] response) + { + final ServerConnection sconn = (ServerConnection) conn; + final SubjectAuthenticationResult authResult = _subjectCreator.authenticate(ss, response); + + if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus())) + { + tuneAuthorizedConnection(sconn); + sconn.setAuthorizedSubject(authResult.getSubject()); + } + else if (AuthenticationStatus.CONTINUE.equals(authResult.getStatus())) + { + connectionAuthContinue(sconn, authResult.getChallenge()); + } + else + { + connectionAuthFailed(sconn, authResult.getCause()); + } + } + + @Override + public void connectionClose(Connection conn, ConnectionClose close) + { + final ServerConnection sconn = (ServerConnection) conn; + try + { + sconn.logClosed(); + } + finally + { + sconn.closeCode(close); + sconn.setState(CLOSE_RCVD); + sendConnectionCloseOkAndCloseSender(conn); + } + } + + public void connectionOpen(Connection conn, ConnectionOpen open) + { + final ServerConnection sconn = (ServerConnection) conn; + + VirtualHost vhost; + String vhostName; + if(open.hasVirtualHost()) + { + vhostName = open.getVirtualHost(); + } + else + { + vhostName = ""; + } + vhost = _broker.getVirtualHostRegistry().getVirtualHost(vhostName); + + SecurityManager.setThreadSubject(sconn.getAuthorizedSubject()); + + if(vhost != null) + { + sconn.setVirtualHost(vhost); + + if (!vhost.getSecurityManager().accessVirtualhost(vhostName, sconn.getRemoteAddress())) + { + sconn.setState(Connection.State.CLOSING); + sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Permission denied '"+vhostName+"'")); + } + else if (vhost.getState() != State.ACTIVE) + { + sconn.setState(Connection.State.CLOSING); + sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Virtual host '"+vhostName+"' is not active")); + } + else + { + sconn.setState(Connection.State.OPEN); + sconn.invoke(new ConnectionOpenOk(Collections.emptyList())); + } + } + else + { + sconn.setState(Connection.State.CLOSING); + sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'")); + } + + } + + @Override + public void connectionTuneOk(final Connection conn, final ConnectionTuneOk ok) + { + ServerConnection sconn = (ServerConnection) conn; + int okChannelMax = ok.getChannelMax(); + + if (okChannelMax > getChannelMax()) + { + LOGGER.error("Connection '" + sconn.getConnectionId() + "' being severed, " + + "client connectionTuneOk returned a channelMax (" + okChannelMax + + ") above the server's offered limit (" + getChannelMax() +")"); + + //Due to the error we must forcefully close the connection without negotiation + sconn.getSender().close(); + return; + } + + final NetworkConnection networkConnection = sconn.getNetworkConnection(); + + if(ok.hasHeartbeat()) + { + int heartbeat = ok.getHeartbeat(); + if(heartbeat < 0) + { + heartbeat = 0; + } + + networkConnection.setMaxReadIdle(2 * heartbeat); + networkConnection.setMaxWriteIdle(heartbeat); + + } + else + { + networkConnection.setMaxReadIdle(0); + networkConnection.setMaxWriteIdle(0); + } + + setConnectionTuneOkChannelMax(sconn, okChannelMax); + } + + @Override + public int getChannelMax() + { + return _maxNoOfChannels; + } + + protected void setChannelMax(int channelMax) + { + _maxNoOfChannels = channelMax; + } + + @Override public void sessionDetach(Connection conn, SessionDetach dtc) + { + // To ensure a clean detach, we stop any remaining subscriptions. Stop ensures + // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the stop + // completes. + stopAllSubscriptions(conn, dtc); + Session ssn = conn.getSession(dtc.getChannel()); + ((ServerSession)ssn).setClose(true); + super.sessionDetach(conn, dtc); + } + + private void stopAllSubscriptions(Connection conn, SessionDetach dtc) + { + final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel()); + final Collection subs = ssn.getSubscriptions(); + for (Subscription_0_10 subscription_0_10 : subs) + { + subscription_0_10.stop(); + } + } + + + @Override + public void sessionAttach(final Connection conn, final SessionAttach atc) + { + final Session ssn; + + if(isSessionNameUnique(atc.getName(), conn)) + { + super.sessionAttach(conn, atc); + } + else + { + ssn = getSession(conn, atc); + ssn.invoke(new SessionDetached(atc.getName(), SessionDetachCode.SESSION_BUSY)); + ssn.closed(); + } + } + + private boolean isSessionNameUnique(final byte[] name, final Connection conn) + { + final ServerConnection sconn = (ServerConnection) conn; + final String userId = sconn.getUserName(); + + final Iterator connections = + ((ServerConnection)conn).getVirtualHost().getConnectionRegistry().getConnections().iterator(); + while(connections.hasNext()) + { + final AMQConnectionModel amqConnectionModel = (AMQConnectionModel) connections.next(); + if (userId.equals(amqConnectionModel.getUserName()) && !amqConnectionModel.isSessionNameUnique(name)) + { + return false; + } + } + return true; + } + + @Override + public void connectionStartOk(Connection conn, ConnectionStartOk ok) + { + _clientProperties = ok.getClientProperties(); + super.connectionStartOk(conn, ok); + } + + public Map getClientProperties() + { + return _clientProperties; + } + + public String getClientId() + { + return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.CLIENT_ID_0_10); + } + + public String getClientVersion() + { + return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.VERSION_0_10); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java new file mode 100644 index 0000000000..abe784cefa --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java @@ -0,0 +1,1000 @@ +/* + * + * 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.v0_10; + +import java.security.Principal; +import java.text.MessageFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import javax.security.auth.Subject; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.TransactionTimeoutHelper; +import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogMessage; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.logging.messages.ChannelMessages; +import org.apache.qpid.server.logging.subjects.ChannelLogSubject; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.AuthorizationHolder; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.txn.AlreadyKnownDtxException; +import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; +import org.apache.qpid.server.txn.DistributedTransaction; +import org.apache.qpid.server.txn.DtxNotSelectedException; +import org.apache.qpid.server.txn.IncorrectDtxStateException; +import org.apache.qpid.server.txn.JoinAndResumeDtxException; +import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.NotAssociatedDtxException; +import org.apache.qpid.server.txn.RollbackOnlyDtxException; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.SuspendAndFailDtxException; +import org.apache.qpid.server.txn.TimeoutDtxException; +import org.apache.qpid.server.txn.UnknownDtxBranchException; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; +import static org.apache.qpid.util.Serial.gt; + +public class ServerSession extends Session + implements AuthorizationHolder, + AMQSessionModel, LogSubject, AsyncAutoCommitTransaction.FutureRecorder +{ + private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class); + + private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); + private static final int PRODUCER_CREDIT_TOPUP_THRESHOLD = 1 << 30; + private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500; + + private final UUID _id = UUID.randomUUID(); + private long _createTime = System.currentTimeMillis(); + private LogActor _actor = GenericActor.getInstance(this); + + private final Set _blockingEntities = Collections.synchronizedSet(new HashSet()); + + private final AtomicBoolean _blocking = new AtomicBoolean(false); + private ChannelLogSubject _logSubject; + private final AtomicInteger _outstandingCredit = new AtomicInteger(UNLIMITED_CREDIT); + + public static interface MessageDispositionChangeListener + { + public void onAccept(); + + public void onRelease(boolean setRedelivered); + + public void onReject(); + + public boolean acquire(); + + + } + + public static interface Task + { + public void doTask(ServerSession session); + } + + + private final SortedMap _messageDispositionListenerMap = + new ConcurrentSkipListMap(); + + private ServerTransaction _transaction; + + private final AtomicLong _txnStarts = new AtomicLong(0); + private final AtomicLong _txnCommits = new AtomicLong(0); + private final AtomicLong _txnRejects = new AtomicLong(0); + private final AtomicLong _txnCount = new AtomicLong(0); + + private Map _subscriptions = new ConcurrentHashMap(); + + private final List _taskList = new CopyOnWriteArrayList(); + + private final TransactionTimeoutHelper _transactionTimeoutHelper; + + private AtomicReference _forcedCloseLogMessage = new AtomicReference(); + + public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) + { + super(connection, delegate, name, expiry); + _transaction = new AsyncAutoCommitTransaction(this.getMessageStore(),this); + _logSubject = new ChannelLogSubject(this); + + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() + { + @Override + public void doTimeoutAction(String reason) throws AMQException + { + getConnectionModel().closeSession(ServerSession.this, AMQConstant.RESOURCE_ERROR, reason); + } + }); + } + + protected void setState(State state) + { + super.setState(state); + + if (state == State.OPEN) + { + _actor.message(ChannelMessages.CREATE()); + if(_blocking.get()) + { + invokeBlock(); + } + } + } + + private void invokeBlock() + { + invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT)); + invoke(new MessageStop("")); + } + + @Override + protected boolean isFull(int id) + { + return isCommandsFull(id); + } + + public void enqueue(final ServerMessage message, final List queues) + { + if(_outstandingCredit.get() != UNLIMITED_CREDIT + && _outstandingCredit.decrementAndGet() == (Integer.MAX_VALUE - PRODUCER_CREDIT_TOPUP_THRESHOLD)) + { + _outstandingCredit.addAndGet(PRODUCER_CREDIT_TOPUP_THRESHOLD); + invoke(new MessageFlow("",MessageCreditUnit.MESSAGE, PRODUCER_CREDIT_TOPUP_THRESHOLD)); + } + getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime()); + PostEnqueueAction postTransactionAction = new PostEnqueueAction(queues, message, isTransactional()) ; + _transaction.enqueue(queues,message, postTransactionAction); + incrementOutstandingTxnsIfNecessary(); + } + + + public void sendMessage(MessageTransfer xfr, + Runnable postIdSettingAction) + { + getConnectionModel().registerMessageDelivered(xfr.getBodySize()); + invoke(xfr, postIdSettingAction); + } + + public void onMessageDispositionChange(MessageTransfer xfr, MessageDispositionChangeListener acceptListener) + { + _messageDispositionListenerMap.put(xfr.getId(), acceptListener); + } + + + private static interface MessageDispositionAction + { + void performAction(MessageDispositionChangeListener listener); + } + + public void accept(RangeSet ranges) + { + dispositionChange(ranges, new MessageDispositionAction() + { + public void performAction(MessageDispositionChangeListener listener) + { + listener.onAccept(); + } + }); + } + + + public void release(RangeSet ranges, final boolean setRedelivered) + { + dispositionChange(ranges, new MessageDispositionAction() + { + public void performAction(MessageDispositionChangeListener listener) + { + listener.onRelease(setRedelivered); + } + }); + } + + public void reject(RangeSet ranges) + { + dispositionChange(ranges, new MessageDispositionAction() + { + public void performAction(MessageDispositionChangeListener listener) + { + listener.onReject(); + } + }); + } + + public RangeSet acquire(RangeSet transfers) + { + RangeSet acquired = RangeSetFactory.createRangeSet(); + + if(!_messageDispositionListenerMap.isEmpty()) + { + Iterator unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); + Iterator rangeIter = transfers.iterator(); + + if(rangeIter.hasNext()) + { + Range range = rangeIter.next(); + + while(range != null && unacceptedMessages.hasNext()) + { + int next = unacceptedMessages.next(); + while(gt(next, range.getUpper())) + { + if(rangeIter.hasNext()) + { + range = rangeIter.next(); + } + else + { + range = null; + break; + } + } + if(range != null && range.includes(next)) + { + MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.get(next); + if(changeListener != null && changeListener.acquire()) + { + acquired.add(next); + } + } + + + } + + } + + + } + + return acquired; + } + + public void dispositionChange(RangeSet ranges, MessageDispositionAction action) + { + if(ranges != null) + { + + if(ranges.size() == 1) + { + Range r = ranges.getFirst(); + for(int i = r.getLower(); i <= r.getUpper(); i++) + { + MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(i); + if(changeListener != null) + { + action.performAction(changeListener); + } + } + } + else if(!_messageDispositionListenerMap.isEmpty()) + { + Iterator unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); + Iterator rangeIter = ranges.iterator(); + + if(rangeIter.hasNext()) + { + Range range = rangeIter.next(); + + while(range != null && unacceptedMessages.hasNext()) + { + int next = unacceptedMessages.next(); + while(gt(next, range.getUpper())) + { + if(rangeIter.hasNext()) + { + range = rangeIter.next(); + } + else + { + range = null; + break; + } + } + if(range != null && range.includes(next)) + { + MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(next); + action.performAction(changeListener); + } + + + } + + } + } + } + } + + public void removeDispositionListener(Method method) + { + _messageDispositionListenerMap.remove(method.getId()); + } + + public void onClose() + { + if(_transaction instanceof LocalTransaction) + { + _transaction.rollback(); + } + else if(_transaction instanceof DistributedTransaction) + { + getVirtualHost().getDtxRegistry().endAssociations(this); + } + + for(MessageDispositionChangeListener listener : _messageDispositionListenerMap.values()) + { + listener.onRelease(true); + } + _messageDispositionListenerMap.clear(); + + for (Task task : _taskList) + { + task.doTask(this); + } + + LogMessage operationalLoggingMessage = _forcedCloseLogMessage.get(); + if (operationalLoggingMessage == null) + { + operationalLoggingMessage = ChannelMessages.CLOSE(); + } + CurrentActor.get().message(getLogSubject(), operationalLoggingMessage); + } + + @Override + protected void awaitClose() + { + // Broker shouldn't block awaiting close - thus do override this method to do nothing + } + + public void acknowledge(final Subscription_0_10 sub, final QueueEntry entry) + { + _transaction.dequeue(entry.getQueue(), entry.getMessage(), + new ServerTransaction.Action() + { + + public void postCommit() + { + sub.acknowledge(entry); + } + + public void onRollback() + { + // The client has acknowledge the message and therefore have seen it. + // In the event of rollback, the message must be marked as redelivered. + entry.setRedelivered(); + entry.release(); + } + }); + } + + public Collection getSubscriptions() + { + return _subscriptions.values(); + } + + public void register(String destination, Subscription_0_10 sub) + { + _subscriptions.put(destination == null ? NULL_DESTINTATION : destination, sub); + } + + public Subscription_0_10 getSubscription(String destination) + { + return _subscriptions.get(destination == null ? NULL_DESTINTATION : destination); + } + + public void unregister(Subscription_0_10 sub) + { + _subscriptions.remove(sub.getName()); + try + { + sub.getSendLock(); + AMQQueue queue = sub.getQueue(); + if(queue != null) + { + queue.unregisterSubscription(sub); + } + } + catch (AMQException e) + { + // TODO + _logger.error("Failed to unregister subscription :" + e.getMessage(), e); + } + finally + { + sub.releaseSendLock(); + } + } + + public boolean isTransactional() + { + return _transaction.isTransactional(); + } + + public void selectTx() + { + _transaction = new LocalTransaction(this.getMessageStore()); + _txnStarts.incrementAndGet(); + } + + public void selectDtx() + { + _transaction = new DistributedTransaction(this, getMessageStore(), getVirtualHost()); + + } + + + public void startDtx(Xid xid, boolean join, boolean resume) + throws JoinAndResumeDtxException, + UnknownDtxBranchException, + AlreadyKnownDtxException, + DtxNotSelectedException + { + DistributedTransaction distributedTransaction = assertDtxTransaction(); + distributedTransaction.start(xid, join, resume); + } + + + public void endDtx(Xid xid, boolean fail, boolean suspend) + throws NotAssociatedDtxException, + UnknownDtxBranchException, + DtxNotSelectedException, + SuspendAndFailDtxException, TimeoutDtxException + { + DistributedTransaction distributedTransaction = assertDtxTransaction(); + distributedTransaction.end(xid, fail, suspend); + } + + + public long getTimeoutDtx(Xid xid) + throws UnknownDtxBranchException + { + return getVirtualHost().getDtxRegistry().getTimeout(xid); + } + + + public void setTimeoutDtx(Xid xid, long timeout) + throws UnknownDtxBranchException + { + getVirtualHost().getDtxRegistry().setTimeout(xid, timeout); + } + + + public void prepareDtx(Xid xid) + throws UnknownDtxBranchException, + IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException + { + getVirtualHost().getDtxRegistry().prepare(xid); + } + + public void commitDtx(Xid xid, boolean onePhase) + throws UnknownDtxBranchException, + IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException + { + getVirtualHost().getDtxRegistry().commit(xid, onePhase); + } + + + public void rollbackDtx(Xid xid) + throws UnknownDtxBranchException, + IncorrectDtxStateException, AMQStoreException, TimeoutDtxException + { + getVirtualHost().getDtxRegistry().rollback(xid); + } + + + public void forgetDtx(Xid xid) throws UnknownDtxBranchException, IncorrectDtxStateException + { + getVirtualHost().getDtxRegistry().forget(xid); + } + + public List recoverDtx() + { + return getVirtualHost().getDtxRegistry().recover(); + } + + private DistributedTransaction assertDtxTransaction() throws DtxNotSelectedException + { + if(_transaction instanceof DistributedTransaction) + { + return (DistributedTransaction) _transaction; + } + else + { + throw new DtxNotSelectedException(); + } + } + + + public void commit() + { + _transaction.commit(); + + _txnCommits.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + + public void rollback() + { + _transaction.rollback(); + + _txnRejects.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + + + private void incrementOutstandingTxnsIfNecessary() + { + if(isTransactional()) + { + //There can currently only be at most one outstanding transaction + //due to only having LocalTransaction support. Set value to 1 if 0. + _txnCount.compareAndSet(0,1); + } + } + + private void decrementOutstandingTxnsIfNecessary() + { + if(isTransactional()) + { + //There can currently only be at most one outstanding transaction + //due to only having LocalTransaction support. Set value to 0 if 1. + _txnCount.compareAndSet(1,0); + } + } + + public Long getTxnCommits() + { + return _txnCommits.get(); + } + + public Long getTxnRejects() + { + return _txnRejects.get(); + } + + public int getChannelId() + { + return getChannel(); + } + + public Long getTxnCount() + { + return _txnCount.get(); + } + + public Long getTxnStart() + { + return _txnStarts.get(); + } + + public Principal getAuthorizedPrincipal() + { + return getConnection().getAuthorizedPrincipal(); + } + + public Subject getAuthorizedSubject() + { + return getConnection().getAuthorizedSubject(); + } + + public void addSessionCloseTask(Task task) + { + _taskList.add(task); + } + + public void removeSessionCloseTask(Task task) + { + _taskList.remove(task); + } + + public Object getReference() + { + return getConnection().getReference(); + } + + public MessageStore getMessageStore() + { + return getVirtualHost().getMessageStore(); + } + + public VirtualHost getVirtualHost() + { + return getConnection().getVirtualHost(); + } + + public boolean isDurable() + { + return false; + } + + + public long getCreateTime() + { + return _createTime; + } + + @Override + public UUID getId() + { + return _id; + } + + public AMQConnectionModel getConnectionModel() + { + return getConnection(); + } + + public String getClientID() + { + return getConnection().getClientId(); + } + + @Override + public ServerConnection getConnection() + { + return (ServerConnection) super.getConnection(); + } + + public LogActor getLogActor() + { + return _actor; + } + + public LogSubject getLogSubject() + { + return (LogSubject) this; + } + + public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException + { + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); + } + + public void block(AMQQueue queue) + { + block(queue, queue.getName()); + } + + public void block() + { + block(this, "** All Queues **"); + } + + + private void block(Object queue, String name) + { + synchronized (_blockingEntities) + { + if(_blockingEntities.add(queue)) + { + + if(_blocking.compareAndSet(false,true)) + { + if(getState() == State.OPEN) + { + invokeBlock(); + } + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(name)); + } + + + } + } + } + + public void unblock(AMQQueue queue) + { + unblock((Object)queue); + } + + public void unblock() + { + unblock(this); + } + + private void unblock(Object queue) + { + synchronized(_blockingEntities) + { + if(_blockingEntities.remove(queue) && _blockingEntities.isEmpty()) + { + if(_blocking.compareAndSet(true,false) && !isClosing()) + { + + _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); + MessageFlow mf = new MessageFlow(); + mf.setUnit(MessageCreditUnit.MESSAGE); + mf.setDestination(""); + _outstandingCredit.set(Integer.MAX_VALUE); + mf.setValue(Integer.MAX_VALUE); + invoke(mf); + + + } + } + } + } + + public boolean onSameConnection(InboundMessage inbound) + { + return ((inbound instanceof MessageTransferMessage) + && ((MessageTransferMessage)inbound).getConnectionReference() == getConnection().getReference()) + || ((inbound instanceof MessageMetaData_0_10) + && (((MessageMetaData_0_10)inbound).getConnectionReference())== getConnection().getReference()); + } + + + public String toLogString() + { + long connectionId = super.getConnection() instanceof ServerConnection + ? getConnection().getConnectionId() + : -1; + + String remoteAddress = String.valueOf(getConnection().getRemoteAddress()); + return "[" + + MessageFormat.format(CHANNEL_FORMAT, + connectionId, + getClientID(), + remoteAddress, + getVirtualHost().getName(), + getChannel()) + + "] "; + } + + @Override + public void close(AMQConstant cause, String message) + { + if (cause == null) + { + close(); + } + else + { + close(cause.getCode(), message); + } + } + + void close(int cause, String message) + { + _forcedCloseLogMessage.compareAndSet(null, ChannelMessages.CLOSE_FORCED(cause, message)); + close(); + } + + @Override + public void close() + { + // unregister subscriptions in order to prevent sending of new messages + // to subscriptions with closing session + unregisterSubscriptions(); + super.close(); + } + + void unregisterSubscriptions() + { + final Collection subscriptions = getSubscriptions(); + for (Subscription_0_10 subscription_0_10 : subscriptions) + { + unregister(subscription_0_10); + } + } + + void stopSubscriptions() + { + final Collection subscriptions = getSubscriptions(); + for (Subscription_0_10 subscription_0_10 : subscriptions) + { + subscription_0_10.stop(); + } + } + + + public void receivedComplete() + { + final Collection subscriptions = getSubscriptions(); + for (Subscription_0_10 subscription_0_10 : subscriptions) + { + subscription_0_10.flushCreditState(false); + } + awaitCommandCompletion(); + } + + private class PostEnqueueAction implements ServerTransaction.Action + { + + private List _queues; + private ServerMessage _message; + private final boolean _transactional; + + public PostEnqueueAction(List queues, ServerMessage message, final boolean transactional) + { + _transactional = transactional; + setState(queues, message); + } + + public void setState(List queues, ServerMessage message) + { + _message = message; + _queues = queues; + } + + public void postCommit() + { + MessageReference ref = _message.newReference(); + for(int i = 0; i < _queues.size(); i++) + { + try + { + BaseQueue queue = _queues.get(i); + queue.enqueue(_message, _transactional, null); + if(queue instanceof AMQQueue) + { + ((AMQQueue)queue).checkCapacity(ServerSession.this); + } + + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + } + ref.release(); + } + + public void onRollback() + { + // NO-OP + } + } + + public int getUnacknowledgedMessageCount() + { + return _messageDispositionListenerMap.size(); + } + + public boolean getBlocking() + { + return _blocking.get(); + } + + private final LinkedList _unfinishedCommandsQueue = new LinkedList(); + + public void completeAsyncCommands() + { + AsyncCommand cmd; + while((cmd = _unfinishedCommandsQueue.peek()) != null && cmd.isReadyForCompletion()) + { + cmd.complete(); + _unfinishedCommandsQueue.poll(); + } + while(_unfinishedCommandsQueue.size() > UNFINISHED_COMMAND_QUEUE_THRESHOLD) + { + cmd = _unfinishedCommandsQueue.poll(); + cmd.awaitReadyForCompletion(); + cmd.complete(); + } + } + + + public void awaitCommandCompletion() + { + AsyncCommand cmd; + while((cmd = _unfinishedCommandsQueue.poll()) != null) + { + cmd.awaitReadyForCompletion(); + cmd.complete(); + } + } + + + public Object getAsyncCommandMark() + { + return _unfinishedCommandsQueue.isEmpty() ? null : _unfinishedCommandsQueue.getLast(); + } + + public void recordFuture(final StoreFuture future, final ServerTransaction.Action action) + { + _unfinishedCommandsQueue.add(new AsyncCommand(future, action)); + } + + private static class AsyncCommand + { + private final StoreFuture _future; + private ServerTransaction.Action _action; + + public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action) + { + _future = future; + _action = action; + } + + void awaitReadyForCompletion() + { + _future.waitForCompletion(); + } + + void complete() + { + if(!_future.isComplete()) + { + _future.waitForCompletion(); + } + _action.postCommit(); + _action = null; + } + + boolean isReadyForCompletion() + { + return _future.isComplete(); + } + } + + protected void setClose(boolean close) + { + super.setClose(close); + } + + @Override + public int getConsumerCount() + { + return _subscriptions.values().size(); + } + + @Override + public int compareTo(AMQSessionModel o) + { + return getId().compareTo(o.getId()); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java new file mode 100644 index 0000000000..08be1fdd2b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java @@ -0,0 +1,1583 @@ +/* + * + * 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.v0_10; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.AMQUnknownExchangeType; +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.ExchangeInUseException; +import org.apache.qpid.server.exchange.HeadersExchange; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.filter.FilterManagerFactory; +import org.apache.qpid.server.logging.messages.ExchangeMessages; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.protocol.v0_8.SubscriptionFactoryImpl; +import org.apache.qpid.server.txn.AlreadyKnownDtxException; +import org.apache.qpid.server.txn.DtxNotSelectedException; +import org.apache.qpid.server.txn.IncorrectDtxStateException; +import org.apache.qpid.server.txn.JoinAndResumeDtxException; +import org.apache.qpid.server.txn.NotAssociatedDtxException; +import org.apache.qpid.server.txn.RollbackOnlyDtxException; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.SuspendAndFailDtxException; +import org.apache.qpid.server.txn.TimeoutDtxException; +import org.apache.qpid.server.txn.UnknownDtxBranchException; +import org.apache.qpid.server.virtualhost.ExchangeExistsException; +import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; +import org.apache.qpid.server.virtualhost.RequiredExchangeException; +import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; +import org.apache.qpid.server.virtualhost.UnknownExchangeException; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.*; + +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class ServerSessionDelegate extends SessionDelegate +{ + private static final Logger LOGGER = Logger.getLogger(ServerSessionDelegate.class); + + /** + * No-local queue argument is used to support the no-local feature of Durable Subscribers. + */ + private static final String QUEUE_ARGUMENT_NO_LOCAL = "no-local"; + + public ServerSessionDelegate() + { + + } + + @Override + public void command(Session session, Method method) + { + try + { + setThreadSubject(session); + + if(!session.isClosing()) + { + Object asyncCommandMark = ((ServerSession)session).getAsyncCommandMark(); + super.command(session, method, false); + Object newOutstanding = ((ServerSession)session).getAsyncCommandMark(); + if(newOutstanding == null || newOutstanding == asyncCommandMark) + { + session.processed(method); + } + + if(newOutstanding != null) + { + ((ServerSession)session).completeAsyncCommands(); + } + + if (method.isSync()) + { + ((ServerSession)session).awaitCommandCompletion(); + session.flushProcessed(); + } + } + } + catch(RuntimeException e) + { + LOGGER.error("Exception processing command", e); + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Exception processing command: " + e); + } + } + + @Override + public void messageAccept(Session session, MessageAccept method) + { + final ServerSession serverSession = (ServerSession) session; + serverSession.accept(method.getTransfers()); + if(!serverSession.isTransactional()) + { + serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE, + new CommandProcessedAction(serverSession, method)); + } + } + + @Override + public void messageReject(Session session, MessageReject method) + { + ((ServerSession)session).reject(method.getTransfers()); + } + + @Override + public void messageRelease(Session session, MessageRelease method) + { + ((ServerSession)session).release(method.getTransfers(), method.getSetRedelivered()); + } + + @Override + public void messageAcquire(Session session, MessageAcquire method) + { + RangeSet acquiredRanges = ((ServerSession)session).acquire(method.getTransfers()); + + Acquired result = new Acquired(acquiredRanges); + + + session.executionResult((int) method.getId(), result); + + + } + + @Override + public void messageResume(Session session, MessageResume method) + { + super.messageResume(session, method); + } + + @Override + public void messageSubscribe(Session session, MessageSubscribe method) + { + /* + TODO - work around broken Python tests + Correct code should read like + if not hasAcceptMode() exception ILLEGAL_ARGUMENT "Accept-mode not supplied" + else if not method.hasAcquireMode() exception ExecutionErrorCode.ILLEGAL_ARGUMENT, "Acquire-mode not supplied" + */ + if(!method.hasAcceptMode()) + { + method.setAcceptMode(MessageAcceptMode.EXPLICIT); + } + if(!method.hasAcquireMode()) + { + method.setAcquireMode(MessageAcquireMode.PRE_ACQUIRED); + + } + + if(!method.hasQueue()) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not supplied"); + } + else + { + String destination = method.getDestination(); + + if(((ServerSession)session).getSubscription(destination)!=null) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Subscription already exists with destination '"+destination+"'"); + } + else + { + String queueName = method.getQueue(); + QueueRegistry queueRegistry = getQueueRegistry(session); + + + final AMQQueue queue = queueRegistry.getQueue(queueName); + + if(queue == null) + { + exception(session,method,ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found"); + } + else if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session) + { + exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); + } + else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session) + { + exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); + } + else + { + if(queue.isExclusive()) + { + ServerSession s = (ServerSession) session; + queue.setExclusiveOwningSession(s); + if(queue.getAuthorizationHolder() == null) + { + queue.setAuthorizationHolder(s); + queue.setExclusiveOwningSession(s); + ((ServerSession) session).addSessionCloseTask(new ServerSession.Task() + { + public void doTask(ServerSession session) + { + if(queue.getAuthorizationHolder() == session) + { + queue.setAuthorizationHolder(null); + queue.setExclusiveOwningSession(null); + } + } + }); + } + } + + FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L); + + FilterManager filterManager = null; + try + { + filterManager = FilterManagerFactory.createManager(method.getArguments()); + } + catch (AMQException amqe) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Exception Creating FilterManager"); + return; + } + + Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session, + destination, + method.getAcceptMode(), + method.getAcquireMode(), + MessageFlowMode.WINDOW, + creditManager, + filterManager, + method.getArguments()); + + ((ServerSession)session).register(destination, sub); + try + { + queue.registerSubscription(sub, method.getExclusive()); + } + catch (AMQQueue.ExistingExclusiveSubscription existing) + { + exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an exclusive consumer"); + } + catch (AMQQueue.ExistingSubscriptionPreventsExclusive exclusive) + { + exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an existing consumer - can't subscribe exclusively"); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot subscribe to queue '" + queueName + "' with destination '" + destination); + } + } + } + } + } + + @Override + public void messageTransfer(Session ssn, final MessageTransfer xfr) + { + final Exchange exchange = getExchangeForMessage(ssn, xfr); + + DeliveryProperties delvProps = null; + if(xfr.getHeader() != null && (delvProps = xfr.getHeader().getDeliveryProperties()) != null && delvProps.hasTtl() && !delvProps + .hasExpiration()) + { + delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); + } + + final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); + messageMetaData.setConnectionReference(((ServerSession)ssn).getReference()); + + if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName())) + { + ExecutionErrorCode errorCode = ExecutionErrorCode.UNAUTHORIZED_ACCESS; + String description = "Permission denied: exchange-name '" + exchange.getName() + "'"; + exception(ssn, xfr, errorCode, description); + + return; + } + + final Exchange exchangeInUse; + List queues = exchange.route(messageMetaData); + if(queues.isEmpty() && exchange.getAlternateExchange() != null) + { + final Exchange alternateExchange = exchange.getAlternateExchange(); + queues = alternateExchange.route(messageMetaData); + if (!queues.isEmpty()) + { + exchangeInUse = alternateExchange; + } + else + { + exchangeInUse = exchange; + } + } + else + { + exchangeInUse = exchange; + } + + final ServerSession serverSession = (ServerSession) ssn; + if(!queues.isEmpty()) + { + final MessageStore store = getVirtualHost(ssn).getMessageStore(); + final StoredMessage storeMessage = createStoreMessage(xfr, messageMetaData, store); + MessageTransferMessage message = new MessageTransferMessage(storeMessage, serverSession.getReference()); + serverSession.enqueue(message, queues); + storeMessage.flushToStore(); + } + else + { + if((delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) + { + RangeSet rejects = RangeSetFactory.createRangeSet(); + rejects.add(xfr.getId()); + MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); + ssn.invoke(reject); + } + else + { + serverSession.getLogActor().message(ExchangeMessages.DISCARDMSG(exchangeInUse.getName(), messageMetaData.getRoutingKey())); + } + } + + + if(serverSession.isTransactional()) + { + serverSession.processed(xfr); + } + else + { + serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE, new CommandProcessedAction(serverSession, xfr)); + } + } + + private StoredMessage createStoreMessage(final MessageTransfer xfr, + final MessageMetaData_0_10 messageMetaData, final MessageStore store) + { + final StoredMessage storeMessage = store.addMessage(messageMetaData); + ByteBuffer body = xfr.getBody(); + if(body != null) + { + storeMessage.addContent(0, body); + } + return storeMessage; + } + + @Override + public void messageCancel(Session session, MessageCancel method) + { + String destination = method.getDestination(); + + Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); + + if(sub == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + } + else + { + AMQQueue queue = sub.getQueue(); + ((ServerSession)session).unregister(sub); + if(!queue.isDeleted() && queue.isExclusive() && queue.getConsumerCount() == 0) + { + queue.setAuthorizationHolder(null); + } + } + } + + @Override + public void messageFlush(Session session, MessageFlush method) + { + String destination = method.getDestination(); + + Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); + + if(sub == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + } + else + { + + try + { + sub.flush(); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot flush subscription '" + destination); + } + } + } + + @Override + public void txSelect(Session session, TxSelect method) + { + // TODO - check current tx mode + ((ServerSession)session).selectTx(); + } + + @Override + public void txCommit(Session session, TxCommit method) + { + // TODO - check current tx mode + ((ServerSession)session).commit(); + } + + @Override + public void txRollback(Session session, TxRollback method) + { + // TODO - check current tx mode + ((ServerSession)session).rollback(); + } + + @Override + public void dtxSelect(Session session, DtxSelect method) + { + // TODO - check current tx mode + ((ServerSession)session).selectDtx(); + } + + @Override + public void dtxStart(Session session, DtxStart method) + { + XaResult result = new XaResult(); + result.setStatus(DtxXaStatus.XA_OK); + try + { + ((ServerSession)session).startDtx(method.getXid(), method.getJoin(), method.getResume()); + session.executionResult(method.getId(), result); + } + catch(JoinAndResumeDtxException e) + { + exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Unknown xid " + method.getXid()); + } + catch(AlreadyKnownDtxException e) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Xid already started an neither join nor " + + "resume set" + method.getXid()); + } + catch(DtxNotSelectedException e) + { + exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); + } + + } + + @Override + public void dtxEnd(Session session, DtxEnd method) + { + XaResult result = new XaResult(); + result.setStatus(DtxXaStatus.XA_OK); + try + { + try + { + ((ServerSession)session).endDtx(method.getXid(), method.getFail(), method.getSuspend()); + } + catch (TimeoutDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBTIMEOUT); + } + session.executionResult(method.getId(), result); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(NotAssociatedDtxException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(DtxNotSelectedException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(SuspendAndFailDtxException e) + { + exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); + } + + } + + @Override + public void dtxCommit(Session session, DtxCommit method) + { + XaResult result = new XaResult(); + result.setStatus(DtxXaStatus.XA_OK); + try + { + try + { + ((ServerSession)session).commitDtx(method.getXid(), method.getOnePhase()); + } + catch (RollbackOnlyDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBROLLBACK); + } + catch (TimeoutDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBTIMEOUT); + } + session.executionResult(method.getId(), result); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + catch(IncorrectDtxStateException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(AMQStoreException e) + { + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public void dtxForget(Session session, DtxForget method) + { + try + { + ((ServerSession)session).forgetDtx(method.getXid()); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + catch(IncorrectDtxStateException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + + } + + @Override + public void dtxGetTimeout(Session session, DtxGetTimeout method) + { + GetTimeoutResult result = new GetTimeoutResult(); + try + { + result.setTimeout(((ServerSession) session).getTimeoutDtx(method.getXid())); + session.executionResult(method.getId(), result); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + } + + @Override + public void dtxPrepare(Session session, DtxPrepare method) + { + XaResult result = new XaResult(); + result.setStatus(DtxXaStatus.XA_OK); + try + { + try + { + ((ServerSession)session).prepareDtx(method.getXid()); + } + catch (RollbackOnlyDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBROLLBACK); + } + catch (TimeoutDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBTIMEOUT); + } + session.executionResult((int) method.getId(), result); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + catch(IncorrectDtxStateException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(AMQStoreException e) + { + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public void dtxRecover(Session session, DtxRecover method) + { + RecoverResult result = new RecoverResult(); + List inDoubt = ((ServerSession)session).recoverDtx(); + result.setInDoubt(inDoubt); + session.executionResult(method.getId(), result); + } + + @Override + public void dtxRollback(Session session, DtxRollback method) + { + + XaResult result = new XaResult(); + result.setStatus(DtxXaStatus.XA_OK); + try + { + try + { + ((ServerSession)session).rollbackDtx(method.getXid()); + } + catch (TimeoutDtxException e) + { + result.setStatus(DtxXaStatus.XA_RBTIMEOUT); + } + session.executionResult(method.getId(), result); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + catch(IncorrectDtxStateException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); + } + catch(AMQStoreException e) + { + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } + + @Override + public void dtxSetTimeout(Session session, DtxSetTimeout method) + { + try + { + ((ServerSession)session).setTimeoutDtx(method.getXid(), method.getTimeout()); + } + catch(UnknownDtxBranchException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); + } + } + + @Override + public void executionSync(final Session ssn, final ExecutionSync sync) + { + ((ServerSession)ssn).awaitCommandCompletion(); + super.executionSync(ssn, sync); + } + + @Override + public void exchangeDeclare(Session session, ExchangeDeclare method) + { + String exchangeName = method.getExchange(); + VirtualHost virtualHost = getVirtualHost(session); + + //we must check for any unsupported arguments present and throw not-implemented + if(method.hasArguments()) + { + Map args = method.getArguments(); + //QPID-3392: currently we don't support any! + if(!args.isEmpty()) + { + exception(session, method, ExecutionErrorCode.NOT_IMPLEMENTED, "Unsupported exchange argument(s) found " + args.keySet().toString()); + return; + } + } + + if(method.getPassive()) + { + Exchange exchange = getExchange(session, exchangeName); + + if(exchange == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: exchange-name '" + exchangeName + "'"); + } + else + { + if (!exchange.getTypeShortString().toString().equals(method.getType()) + && (method.getType() != null && method.getType().length() > 0)) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " + + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() + "."); + } + } + } + else + { + + try + { + virtualHost.createExchange(null, + method.getExchange(), + method.getType(), + method.getDurable(), + method.getAutoDelete(), + method.getAlternateExchange()); + } + catch(ReservedExchangeNameException e) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to declare exchange: " + + exchangeName + " which begins with reserved name or prefix."); + } + catch(UnknownExchangeException e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, + "Unknown alternate exchange " + e.getExchangeName()); + } + catch(AMQUnknownExchangeType e) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType()); + } + catch(ExchangeExistsException e) + { + Exchange exchange = e.getExistingExchange(); + if(!exchange.getTypeShortString().toString().equals(method.getType())) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, + "Attempt to redeclare exchange: " + exchangeName + + " of type " + exchange.getTypeShortString() + + " to " + method.getType() +"."); + } + else if(method.hasAlternateExchange() + && (exchange.getAlternateExchange() == null || + !method.getAlternateExchange().equals(exchange.getAlternateExchange().getName()))) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, + "Attempt to change alternate exchange of: " + exchangeName + + " from " + exchange.getAlternateExchange() + + " to " + method.getAlternateExchange() +"."); + } + } + catch (AMQException e) + { + exception(session, method, e, "Cannot declare exchange '" + exchangeName); + } + + + } + + } + + // TODO decouple AMQException and AMQConstant error codes + private void exception(Session session, Method method, AMQException exception, String message) + { + ExecutionErrorCode errorCode = ExecutionErrorCode.INTERNAL_ERROR; + if (exception.getErrorCode() != null) + { + try + { + errorCode = ExecutionErrorCode.get(exception.getErrorCode().getCode()); + } + catch (IllegalArgumentException iae) + { + // ignore, already set to INTERNAL_ERROR + } + } + String description = message + "': " + exception.getMessage(); + + exception(session, method, errorCode, description); + } + + private void exception(Session session, Method method, ExecutionErrorCode errorCode, String description) + { + ExecutionException ex = new ExecutionException(); + ex.setErrorCode(errorCode); + ex.setCommandId(method.getId()); + ex.setDescription(description); + + session.invoke(ex); + + ((ServerSession)session).close(errorCode.getValue(), description); + } + + private Exchange getExchange(Session session, String exchangeName) + { + return getVirtualHost(session).getExchange(exchangeName); + } + + private Exchange getExchangeForMessage(Session ssn, MessageTransfer xfr) + { + VirtualHost virtualHost = getVirtualHost(ssn); + + Exchange exchange; + if(xfr.hasDestination()) + { + exchange = virtualHost.getExchange(xfr.getDestination()); + if(exchange == null) + { + exchange = virtualHost.getDefaultExchange(); + } + } + else + { + exchange = virtualHost.getDefaultExchange(); + } + return exchange; + } + + private VirtualHost getVirtualHost(Session session) + { + ServerConnection conn = getServerConnection(session); + VirtualHost vhost = conn.getVirtualHost(); + return vhost; + } + + private ServerConnection getServerConnection(Session session) + { + ServerConnection conn = (ServerConnection) session.getConnection(); + return conn; + } + + @Override + public void exchangeDelete(Session session, ExchangeDelete method) + { + VirtualHost virtualHost = getVirtualHost(session); + + try + { + if (nameNullOrEmpty(method.getExchange())) + { + exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Delete not allowed for default exchange"); + return; + } + + Exchange exchange = getExchange(session, method.getExchange()); + + if(exchange == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "No such exchange '" + method.getExchange() + "'"); + } + else + { + virtualHost.removeExchange(exchange, !method.getIfUnused()); + } + } + catch (ExchangeInUseException e) + { + exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Exchange in use"); + } + catch (ExchangeIsAlternateException e) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Exchange in use as an alternate exchange"); + } + catch (RequiredExchangeException e) + { + exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Exchange '"+method.getExchange()+"' cannot be deleted"); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot delete exchange '" + method.getExchange() ); + } + } + + private boolean nameNullOrEmpty(String name) + { + if(name == null || name.length() == 0) + { + return true; + } + + return false; + } + + private boolean isStandardExchange(Exchange exchange, Collection> registeredTypes) + { + for(ExchangeType type : registeredTypes) + { + if(type.getDefaultExchangeName().toString().equals( exchange.getName() )) + { + return true; + } + } + return false; + } + + @Override + public void exchangeQuery(Session session, ExchangeQuery method) + { + + ExchangeQueryResult result = new ExchangeQueryResult(); + + Exchange exchange = getExchange(session, method.getName()); + + if(exchange != null) + { + result.setDurable(exchange.isDurable()); + result.setType(exchange.getTypeShortString().toString()); + result.setNotFound(false); + } + else + { + result.setNotFound(true); + } + + session.executionResult((int) method.getId(), result); + } + + @Override + public void exchangeBind(Session session, ExchangeBind method) + { + + VirtualHost virtualHost = getVirtualHost(session); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + + if (!method.hasQueue()) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set"); + } + else if (nameNullOrEmpty(method.getExchange())) + { + exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Bind not allowed for default exchange"); + } + else + { + //TODO - here because of non-compiant python tests + // should raise exception ILLEGAL_ARGUMENT "binding-key not set" + if (!method.hasBindingKey()) + { + method.setBindingKey(method.getQueue()); + } + AMQQueue queue = queueRegistry.getQueue(method.getQueue()); + Exchange exchange = virtualHost.getExchange(method.getExchange()); + if(queue == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found"); + } + else if(exchange == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found"); + } + else if(exchange.getTypeShortString().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) + { + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getName() + " require an x-match header"); + } + else + { + if (!exchange.isBound(method.getBindingKey(), method.getArguments(), queue)) + { + try + { + exchange.addBinding(method.getBindingKey(), queue, method.getArguments()); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot add binding '" + method.getBindingKey()); + } + } + else + { + // todo + } + } + + + } + + + + } + + @Override + public void exchangeUnbind(Session session, ExchangeUnbind method) + { + VirtualHost virtualHost = getVirtualHost(session); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + + if (!method.hasQueue()) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set"); + } + else if (nameNullOrEmpty(method.getExchange())) + { + exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Unbind not allowed for default exchange"); + } + else if (!method.hasBindingKey()) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "binding-key not set"); + } + else + { + AMQQueue queue = queueRegistry.getQueue(method.getQueue()); + Exchange exchange = virtualHost.getExchange(method.getExchange()); + if(queue == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found"); + } + else if(exchange == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found"); + } + else + { + try + { + exchange.removeBinding(method.getBindingKey(), queue, null); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot remove binding '" + method.getBindingKey()); + } + } + } + } + + @Override + public void exchangeBound(Session session, ExchangeBound method) + { + + ExchangeBoundResult result = new ExchangeBoundResult(); + VirtualHost virtualHost = getVirtualHost(session); + Exchange exchange; + AMQQueue queue; + if(method.hasExchange()) + { + exchange = virtualHost.getExchange(method.getExchange()); + + if(exchange == null) + { + result.setExchangeNotFound(true); + } + } + else + { + exchange = virtualHost.getDefaultExchange(); + } + + + if(method.hasQueue()) + { + + queue = getQueue(session, method.getQueue()); + if(queue == null) + { + result.setQueueNotFound(true); + } + + + if(exchange != null && queue != null) + { + + boolean queueMatched = exchange.isBound(queue); + + result.setQueueNotMatched(!queueMatched); + + + if(method.hasBindingKey()) + { + + if(queueMatched) + { + final boolean keyMatched = exchange.isBound(method.getBindingKey(), queue); + result.setKeyNotMatched(!keyMatched); + if(method.hasArguments()) + { + if(keyMatched) + { + result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments(), queue)); + } + else + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments(), queue)); + } + } + } + else + { + boolean keyMatched = exchange.isBound(method.getBindingKey()); + result.setKeyNotMatched(!keyMatched); + if(method.hasArguments()) + { + if(keyMatched) + { + result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); + } + else + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments())); + } + } + } + + } + else if (method.hasArguments()) + { + if(queueMatched) + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments(), queue)); + } + else + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments())); + } + } + + } + else if(exchange != null && method.hasBindingKey()) + { + final boolean keyMatched = exchange.isBound(method.getBindingKey()); + result.setKeyNotMatched(!keyMatched); + + if(method.hasArguments()) + { + if(keyMatched) + { + result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); + } + else + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments())); + } + } + + + } + + } + else if(exchange != null && method.hasBindingKey()) + { + final boolean keyMatched = exchange.isBound(method.getBindingKey()); + result.setKeyNotMatched(!keyMatched); + + if(method.hasArguments()) + { + if(keyMatched) + { + result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); + } + else + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments())); + } + } + + } + else if(exchange != null && method.hasArguments()) + { + result.setArgsNotMatched(!exchange.isBound(method.getArguments())); + } + + + session.executionResult((int) method.getId(), result); + + + } + + private AMQQueue getQueue(Session session, String queue) + { + QueueRegistry queueRegistry = getQueueRegistry(session); + return queueRegistry.getQueue(queue); + } + + private QueueRegistry getQueueRegistry(Session session) + { + return getVirtualHost(session).getQueueRegistry(); + } + + @Override + public void queueDeclare(Session session, final QueueDeclare method) + { + + VirtualHost virtualHost = getVirtualHost(session); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + + String queueName = method.getQueue(); + AMQQueue queue; + QueueRegistry queueRegistry = getQueueRegistry(session); + //TODO: do we need to check that the queue already exists with exactly the same "configuration"? + + synchronized (queueRegistry) + { + + if (((queue = queueRegistry.getQueue(queueName)) == null)) + { + + if (method.getPassive()) + { + String description = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; + ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_FOUND; + + exception(session, method, errorCode, description); + + return; + } + else + { + try + { + queue = createQueue(queueName, method, virtualHost, (ServerSession)session); + if(!method.getExclusive() && method.getAutoDelete()) + { + queue.setDeleteOnNoConsumers(true); + } + + final String alternateExchangeName = method.getAlternateExchange(); + if(alternateExchangeName != null && alternateExchangeName.length() != 0) + { + Exchange alternate = getExchange(session, alternateExchangeName); + queue.setAlternateExchange(alternate); + } + + if(method.hasArguments() && method.getArguments() != null) + { + if(method.getArguments().containsKey(QUEUE_ARGUMENT_NO_LOCAL)) + { + Object noLocal = method.getArguments().get(QUEUE_ARGUMENT_NO_LOCAL); + queue.setNoLocal(convertBooleanValue(noLocal)); + } + } + + + if (queue.isDurable() && !queue.isAutoDelete()) + { + if(method.hasArguments() && method.getArguments() != null) + { + Map args = method.getArguments(); + FieldTable ftArgs = new FieldTable(); + for(Map.Entry entry : args.entrySet()) + { + ftArgs.put(new AMQShortString(entry.getKey()), entry.getValue()); + } + DurableConfigurationStoreHelper.createQueue(store, queue, ftArgs); + } + else + { + DurableConfigurationStoreHelper.createQueue(store, queue, null); + } + } + queueRegistry.registerQueue(queue); + + if (method.hasAutoDelete() + && method.getAutoDelete() + && method.hasExclusive() + && method.getExclusive()) + { + final AMQQueue q = queue; + final ServerSession.Task deleteQueueTask = new ServerSession.Task() + { + public void doTask(ServerSession session) + { + try + { + q.delete(); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot delete '" + method.getQueue()); + } + } + }; + final ServerSession s = (ServerSession) session; + s.addSessionCloseTask(deleteQueueTask); + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) throws AMQException + { + s.removeSessionCloseTask(deleteQueueTask); + } + }); + } + if (method.hasExclusive() + && method.getExclusive()) + { + final AMQQueue q = queue; + final ServerSession.Task removeExclusive = new ServerSession.Task() + { + public void doTask(ServerSession session) + { + q.setAuthorizationHolder(null); + q.setExclusiveOwningSession(null); + } + }; + final ServerSession s = (ServerSession) session; + q.setExclusiveOwningSession(s); + s.addSessionCloseTask(removeExclusive); + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) throws AMQException + { + s.removeSessionCloseTask(removeExclusive); + } + }); + } + } + catch (AMQException e) + { + exception(session, method, e, "Cannot declare queue '" + queueName); + } + } + } + else if (method.getExclusive() && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session))) + { + String description = "Cannot declare queue('" + queueName + "')," + + " as exclusive queue with same name " + + "declared on another session"; + ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED; + + exception(session, method, errorCode, description); + + return; + } + } + } + + /** + * Converts a queue argument into a boolean value. For compatibility with the C++ + * and the clients, accepts with Boolean, String, or Number types. + * @param argValue argument value. + * + * @return true if set + */ + private boolean convertBooleanValue(Object argValue) + { + if(argValue instanceof Boolean && ((Boolean)argValue)) + { + return true; + } + else if (argValue instanceof String && Boolean.parseBoolean((String)argValue)) + { + return true; + } + else if (argValue instanceof Number && ((Number)argValue).intValue() != 0) + { + return true; + } + return false; + } + + protected AMQQueue createQueue(final String queueName, + final QueueDeclare body, + VirtualHost virtualHost, + final ServerSession session) + throws AMQException + { + String owner = body.getExclusive() ? session.getClientID() : null; + + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()), queueName, body.getDurable(), owner, + body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments()); + + return queue; + } + + @Override + public void queueDelete(Session session, QueueDelete method) + { + String queueName = method.getQueue(); + if(queueName == null || queueName.length()==0) + { + exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "No queue name supplied"); + + } + else + { + AMQQueue queue = getQueue(session, queueName); + + + if (queue == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found"); + } + else + { + if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session) + { + exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); + } + else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session) + { + exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); + } + else if (method.getIfEmpty() && !queue.isEmpty()) + { + exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " not empty"); + } + else if (method.getIfUnused() && !queue.isUnused()) + { + // TODO - Error code + exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " in use"); + + } + else + { + VirtualHost virtualHost = getVirtualHost(session); + + try + { + queue.delete(); + if (queue.isDurable() && !queue.isAutoDelete()) + { + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + DurableConfigurationStoreHelper.removeQueue(store,queue); + } + } + catch (AMQException e) + { + exception(session, method, e, "Cannot delete queue '" + queueName); + } + } + } + } + } + + @Override + public void queuePurge(Session session, QueuePurge method) + { + String queueName = method.getQueue(); + if(queueName == null || queueName.length()==0) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "No queue name supplied"); + } + else + { + AMQQueue queue = getQueue(session, queueName); + + if (queue == null) + { + exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found"); + } + else + { + try + { + queue.clearQueue(); + } + catch (AMQException e) + { + exception(session, method, e, "Cannot purge queue '" + queueName); + } + } + } + } + + @Override + public void queueQuery(Session session, QueueQuery method) + { + QueueQueryResult result = new QueueQueryResult(); + + AMQQueue queue = getQueue(session, method.getQueue()); + + if(queue != null) + { + result.setQueue(queue.getNameShortString().toString()); + result.setDurable(queue.isDurable()); + result.setExclusive(queue.isExclusive()); + result.setAutoDelete(queue.isAutoDelete()); + result.setArguments(queue.getArguments()); + result.setMessageCount(queue.getMessageCount()); + result.setSubscriberCount(queue.getConsumerCount()); + + } + + + session.executionResult((int) method.getId(), result); + + } + + @Override + public void messageSetFlowMode(Session session, MessageSetFlowMode sfm) + { + String destination = sfm.getDestination(); + + Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); + + if(sub == null) + { + exception(session, sfm, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + } + else if(sub.isStopped()) + { + sub.setFlowMode(sfm.getFlowMode()); + } + } + + @Override + public void messageStop(Session session, MessageStop stop) + { + String destination = stop.getDestination(); + + Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); + + if(sub == null) + { + exception(session, stop, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + } + else + { + sub.stop(); + } + + } + + @Override + public void messageFlow(Session session, MessageFlow flow) + { + String destination = flow.getDestination(); + + Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); + + if(sub == null) + { + exception(session, flow, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + } + else + { + sub.addCredit(flow.getUnit(), flow.getValue()); + } + + } + + @Override + public void closed(Session session) + { + setThreadSubject(session); + + ServerSession serverSession = (ServerSession)session; + + serverSession.stopSubscriptions(); + serverSession.onClose(); + serverSession.unregisterSubscriptions(); + } + + @Override + public void detached(Session session) + { + closed(session); + } + + private void setThreadSubject(Session session) + { + final ServerConnection scon = (ServerConnection) session.getConnection(); + SecurityManager.setThreadSubject(scon.getAuthorizedSubject()); + } + + private static class CommandProcessedAction implements ServerTransaction.Action + { + private final ServerSession _serverSession; + private final Method _method; + + public CommandProcessedAction(final ServerSession serverSession, final Method xfr) + { + _serverSession = serverSession; + _method = xfr; + } + + public void postCommit() + { + _serverSession.processed(_method); + } + + public void onRollback() + { + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java new file mode 100644 index 0000000000..68b956978a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java @@ -0,0 +1,1073 @@ +/* + * + * 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.v0_10; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.logging.messages.ChannelMessages; +import org.apache.qpid.server.logging.messages.SubscriptionMessages; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.InboundMessageAdapter; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.ServerTransaction; +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.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageFlowMode; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Method; +import org.apache.qpid.transport.Option; +import org.apache.qpid.transport.ReplyTo; +import org.apache.qpid.transport.Struct; +import org.apache.qpid.url.AMQBindingURL; + +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.QUEUE_FORMAT; +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT; + +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, LogSubject +{ + private final long _subscriptionID; + + private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + + private static final Option[] BATCHED = new Option[] { Option.BATCH }; + + private final Lock _stateChangeLock = new ReentrantLock(); + + private final AtomicReference _state = new AtomicReference(State.ACTIVE); + private volatile AMQQueue.Context _queueContext; + private final AtomicBoolean _deleted = new AtomicBoolean(false); + + + private FlowCreditManager_0_10 _creditManager; + + private StateListener _stateListener = new StateListener() + { + + public void stateChange(Subscription sub, State oldState, State newState) + { + CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString())); + } + }; + private AMQQueue _queue; + private final String _destination; + private boolean _noLocal; + private final FilterManager _filters; + private final MessageAcceptMode _acceptMode; + private final MessageAcquireMode _acquireMode; + private MessageFlowMode _flowMode; + private final ServerSession _session; + private final AtomicBoolean _stopped = new AtomicBoolean(true); + private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0]; + + private LogActor _logActor; + private final Map _properties = new ConcurrentHashMap(); + private String _traceExclude; + private String _trace; + private final long _createTime = System.currentTimeMillis(); + private final AtomicLong _deliveredCount = new AtomicLong(0); + private final AtomicLong _deliveredBytes = new AtomicLong(0); + private final AtomicLong _unacknowledgedCount = new AtomicLong(0); + private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); + + private final Map _arguments; + private int _deferredMessageCredit; + private long _deferredSizeCredit; + + + public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode, + MessageAcquireMode acquireMode, + MessageFlowMode flowMode, + FlowCreditManager_0_10 creditManager, + FilterManager filters,Map arguments, long subscriptionId) + { + _subscriptionID = subscriptionId; + _session = session; + _postIdSettingAction = new AddMessageDispositionListenerAction(session); + _destination = destination; + _acceptMode = acceptMode; + _acquireMode = acquireMode; + _creditManager = creditManager; + _flowMode = flowMode; + _filters = filters; + _creditManager.addStateListener(this); + _arguments = arguments == null ? Collections. emptyMap() : + Collections. unmodifiableMap(arguments); + _state.set(_creditManager.hasCredit() ? State.ACTIVE : State.SUSPENDED); + + } + + public void setNoLocal(boolean noLocal) + { + _noLocal = noLocal; + } + + public AMQQueue getQueue() + { + return _queue; + } + + public QueueEntry.SubscriptionAcquiredState getOwningState() + { + return _owningState; + } + + public void setQueue(AMQQueue queue, boolean exclusive) + { + if(getQueue() != null) + { + throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); + } + _queue = queue; + + Map arguments = queue.getArguments(); + _traceExclude = (String) arguments.get("qpid.trace.exclude"); + _trace = (String) arguments.get("qpid.trace.id"); + String filterLogString = null; + + _logActor = GenericActor.getInstance(this); + if (CurrentActor.get().getRootMessageLogger().isMessageEnabled(_logActor, this, SubscriptionMessages.CREATE_LOG_HIERARCHY)) + { + filterLogString = getFilterLogString(); + CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive, + filterLogString.length() > 0)); + } + } + + public String getConsumerName() + { + return _destination; + } + + public boolean isSuspended() + { + return !isActive() || _deleted.get() || _session.isClosing() || _session.getConnectionModel().isStopped(); // TODO check for Session suspension + } + + public boolean hasInterest(QueueEntry entry) + { + + + + //check that the message hasn't been rejected + if (entry.isRejectedBy(getSubscriptionID())) + { + + return false; + } + + if (_noLocal && entry.getMessage() instanceof MessageTransferMessage) + { + Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference(); + if (connectionRef != null && connectionRef == _session.getReference()) + { + return false; + } + } + + + return checkFilters(entry); + + + } + + private boolean checkFilters(QueueEntry entry) + { + return (_filters == null) || _filters.allAllow(entry); + } + + public boolean isClosed() + { + return getState() == State.CLOSED; + } + + public boolean isBrowser() + { + return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; + } + + public boolean seesRequeues() + { + return _acquireMode != MessageAcquireMode.NOT_ACQUIRED || _acceptMode == MessageAcceptMode.EXPLICIT; + } + + 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); + CurrentActor.get().message(getLogSubject(), SubscriptionMessages.CLOSE()); + } + finally + { + _stateChangeLock.unlock(); + } + + + + } + + public Long getDelivered() + { + return _deliveredCount.get(); + } + + 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 static class AddMessageDispositionListenerAction implements Runnable + { + private MessageTransfer _xfr; + private ServerSession.MessageDispositionChangeListener _action; + private ServerSession _session; + + public AddMessageDispositionListenerAction(ServerSession session) + { + _session = session; + } + + public void setXfr(MessageTransfer xfr) + { + _xfr = xfr; + } + + public void setAction(ServerSession.MessageDispositionChangeListener action) + { + _action = action; + } + + public void run() + { + if(_action != null) + { + _session.onMessageDispositionChange(_xfr, _action); + } + } + } + + private final AddMessageDispositionListenerAction _postIdSettingAction; + + public void send(final QueueEntry entry, boolean batch) throws AMQException + { + ServerMessage serverMsg = entry.getMessage(); + + + MessageTransfer xfr; + + DeliveryProperties deliveryProps; + MessageProperties messageProps = null; + + if(serverMsg instanceof MessageTransferMessage) + { + + MessageTransferMessage msg = (MessageTransferMessage) serverMsg; + DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties(); + messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties(); + + deliveryProps = new DeliveryProperties(); + if(origDeliveryProps != null) + { + if(origDeliveryProps.hasDeliveryMode()) + { + deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); + } + if(origDeliveryProps.hasExchange()) + { + deliveryProps.setExchange(origDeliveryProps.getExchange()); + } + if(origDeliveryProps.hasExpiration()) + { + deliveryProps.setExpiration(origDeliveryProps.getExpiration()); + } + if(origDeliveryProps.hasPriority()) + { + deliveryProps.setPriority(origDeliveryProps.getPriority()); + } + if(origDeliveryProps.hasRoutingKey()) + { + deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); + } + if(origDeliveryProps.hasTimestamp()) + { + deliveryProps.setTimestamp(origDeliveryProps.getTimestamp()); + } + if(origDeliveryProps.hasTtl()) + { + deliveryProps.setTtl(origDeliveryProps.getTtl()); + } + + + } + + deliveryProps.setRedelivered(entry.isRedelivered()); + + if(_trace != null && messageProps == null) + { + messageProps = new MessageProperties(); + } + + Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties()); + + + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); + } + else if(serverMsg instanceof AMQMessage) + { + AMQMessage message_0_8 = (AMQMessage) serverMsg; + deliveryProps = new DeliveryProperties(); + messageProps = new MessageProperties(); + + int size = (int) message_0_8.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + message_0_8.getContent(body, 0); + body.flip(); + + BasicContentHeaderProperties properties = + (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties(); + final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); + if(exchange != null) + { + deliveryProps.setExchange(exchange.toString()); + } + deliveryProps.setExpiration(message_0_8.getExpiration()); + deliveryProps.setImmediate(message_0_8.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority())); + deliveryProps.setRedelivered(entry.isRedelivered()); + deliveryProps.setRoutingKey(message_0_8.getRoutingKey()); + deliveryProps.setTimestamp(properties.getTimestamp()); + + messageProps.setContentEncoding(properties.getEncodingAsString()); + messageProps.setContentLength(size); + if(properties.getAppId() != null) + { + messageProps.setAppId(properties.getAppId().getBytes()); + } + messageProps.setContentType(properties.getContentTypeAsString()); + if(properties.getCorrelationId() != null) + { + messageProps.setCorrelationId(properties.getCorrelationId().getBytes()); + } + + if(properties.getReplyTo() != null && properties.getReplyTo().length() != 0) + { + String origReplyToString = properties.getReplyTo().asString(); + ReplyTo replyTo = new ReplyTo(); + // if the string looks like a binding URL, then attempt to parse it... + try + { + AMQBindingURL burl = new AMQBindingURL(origReplyToString); + AMQShortString routingKey = burl.getRoutingKey(); + if(routingKey != null) + { + replyTo.setRoutingKey(routingKey.asString()); + } + + AMQShortString exchangeName = burl.getExchangeName(); + if(exchangeName != null) + { + replyTo.setExchange(exchangeName.asString()); + } + } + catch (URISyntaxException e) + { + replyTo.setRoutingKey(origReplyToString); + } + messageProps.setReplyTo(replyTo); + + } + + if(properties.getMessageId() != null) + { + try + { + String messageIdAsString = properties.getMessageIdAsString(); + if(messageIdAsString.startsWith("ID:")) + { + messageIdAsString = messageIdAsString.substring(3); + } + UUID uuid = UUID.fromString(messageIdAsString); + messageProps.setMessageId(uuid); + } + catch(IllegalArgumentException e) + { + // ignore - can't parse + } + } + + + + if(properties.getUserId() != null) + { + messageProps.setUserId(properties.getUserId().getBytes()); + } + + FieldTable fieldTable = properties.getHeaders(); + + Map appHeaders = FieldTable.convertToMap(fieldTable); + + if(properties.getType() != null) + { + appHeaders.put("x-jms-type", properties.getTypeAsString()); + } + + + messageProps.setApplicationHeaders(appHeaders); + + Header header = new Header(deliveryProps, messageProps, null); + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + } + else + { + + deliveryProps = new DeliveryProperties(); + messageProps = new MessageProperties(); + + int size = (int) serverMsg.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + serverMsg.getContent(body, 0); + body.flip(); + + + deliveryProps.setExpiration(serverMsg.getExpiration()); + deliveryProps.setImmediate(serverMsg.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); + deliveryProps.setRedelivered(entry.isRedelivered()); + deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); + deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + + messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); + messageProps.setContentLength(size); + messageProps.setContentType(serverMsg.getMessageHeader().getMimeType()); + if(serverMsg.getMessageHeader().getCorrelationId() != null) + { + messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); + } + + // TODO - ReplyTo + + Header header = new Header(deliveryProps, messageProps, null); + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + } + + boolean excludeDueToFederation = false; + + if(_trace != null) + { + if(!messageProps.hasApplicationHeaders()) + { + messageProps.setApplicationHeaders(new HashMap()); + } + Map appHeaders = messageProps.getApplicationHeaders(); + String trace = (String) appHeaders.get("x-qpid.trace"); + if(trace == null) + { + trace = _trace; + } + else + { + if(_traceExclude != null) + { + excludeDueToFederation = Arrays.asList(trace.split(",")).contains(_traceExclude); + } + trace+=","+_trace; + } + appHeaders.put("x-qpid.trace",trace); + } + + if(!excludeDueToFederation) + { + if(_acceptMode == MessageAcceptMode.NONE && _acquireMode != MessageAcquireMode.PRE_ACQUIRED) + { + xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW)); + } + else if(_flowMode == MessageFlowMode.WINDOW) + { + xfr.setCompletionListener(new Method.CompletionListener() + { + public void onComplete(Method method) + { + deferredAddCredit(1, entry.getSize()); + } + }); + } + + + _postIdSettingAction.setXfr(xfr); + if(_acceptMode == MessageAcceptMode.EXPLICIT) + { + _postIdSettingAction.setAction(new ExplicitAcceptDispositionChangeListener(entry, this)); + } + else if(_acquireMode != MessageAcquireMode.PRE_ACQUIRED) + { + _postIdSettingAction.setAction(new ImplicitAcceptDispositionChangeListener(entry, this)); + } + else + { + _postIdSettingAction.setAction(null); + } + + + _session.sendMessage(xfr, _postIdSettingAction); + entry.incrementDeliveryCount(); + _deliveredCount.incrementAndGet(); + _deliveredBytes.addAndGet(entry.getSize()); + if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED) + { + forceDequeue(entry, false); + } + else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED) + { + recordUnacknowledged(entry); + } + } + else + { + forceDequeue(entry, _flowMode == MessageFlowMode.WINDOW); + + } + } + + void recordUnacknowledged(QueueEntry entry) + { + _unacknowledgedCount.incrementAndGet(); + _unacknowledgedBytes.addAndGet(entry.getSize()); + } + + private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit) + { + _deferredMessageCredit += deferredMessageCredit; + _deferredSizeCredit += deferredSizeCredit; + + } + + public void flushCreditState(boolean strict) + { + if(strict || !isSuspended() || _deferredMessageCredit >= 200 + || !(_creditManager instanceof WindowCreditManager) + || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 ) + { + _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit); + _deferredMessageCredit = 0; + _deferredSizeCredit = 0l; + } + } + + private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) + { + AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); + dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(), + new ServerTransaction.Action() + { + public void postCommit() + { + if (restoreCredit) + { + restoreCredit(entry); + } + entry.discard(); + } + + public void onRollback() + { + + } + }); + } + + void reject(final QueueEntry entry) + { + entry.setRedelivered(); + entry.routeToAlternate(); + if(entry.isAcquiredBy(this)) + { + entry.discard(); + } + } + + void release(final QueueEntry entry, final boolean setRedelivered) + { + if (setRedelivered) + { + entry.setRedelivered(); + } + + if (getSessionModel().isClosing() || !setRedelivered) + { + entry.decrementDeliveryCount(); + } + + if (isMaxDeliveryLimitReached(entry)) + { + sendToDLQOrDiscard(entry); + } + else + { + entry.release(); + } + } + + protected void sendToDLQOrDiscard(QueueEntry entry) + { + final Exchange alternateExchange = entry.getQueue().getAlternateExchange(); + final LogActor logActor = CurrentActor.get(); + final ServerMessage msg = entry.getMessage(); + if (alternateExchange != null) + { + final InboundMessage m = new InboundMessageAdapter(entry); + + final List destinationQueues = alternateExchange.route(m); + + if (destinationQueues == null || destinationQueues.isEmpty()) + { + entry.discard(); + + logActor.message( ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), alternateExchange.getName())); + } + else + { + entry.routeToAlternate(); + + //output operational logging for each delivery post commit + for (final BaseQueue destinationQueue : destinationQueues) + { + logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); + } + } + } + else + { + entry.discard(); + logActor.message(ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), entry.getQueue().getName(), msg.getRoutingKey())); + } + } + + private boolean isMaxDeliveryLimitReached(QueueEntry entry) + { + final int maxDeliveryLimit = entry.getQueue().getMaximumDeliveryCount(); + return (maxDeliveryLimit > 0 && entry.getDeliveryCount() >= maxDeliveryLimit); + } + + public void queueDeleted(AMQQueue queue) + { + _deleted.set(true); + } + + public boolean wouldSuspend(QueueEntry entry) + { + return !_creditManager.useCreditForMessage(entry.getMessage().getSize()); + } + + public boolean trySendLock() + { + return _stateChangeLock.tryLock(); + } + + + public void getSendLock() + { + _stateChangeLock.lock(); + } + + public void releaseSendLock() + { + _stateChangeLock.unlock(); + } + + public void restoreCredit(QueueEntry queueEntry) + { + _creditManager.restoreCredit(1, queueEntry.getSize()); + } + + public void onDequeue(QueueEntry queueEntry) + { + // no-op for 0-10, credit restored by completing command. + } + + public void releaseQueueEntry(QueueEntry queueEntry) + { + // no-op for 0-10, credit restored by completing command. + } + + public void setStateListener(StateListener listener) + { + _stateListener = listener; + } + + public State getState() + { + return _state.get(); + } + + public AMQQueue.Context getQueueContext() + { + return _queueContext; + } + + public void setQueueContext(AMQQueue.Context queueContext) + { + _queueContext = queueContext; + } + + public boolean isActive() + { + return getState() == State.ACTIVE; + } + + public void set(String key, Object value) + { + _properties.put(key, value); + } + + public Object get(String key) + { + return _properties.get(key); + } + + + public FlowCreditManager_0_10 getCreditManager() + { + return _creditManager; + } + + + public void stop() + { + try + { + getSendLock(); + + if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED)) + { + _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED); + } + _stopped.set(true); + FlowCreditManager_0_10 creditManager = getCreditManager(); + creditManager.clearCredit(); + } + finally + { + releaseSendLock(); + } + } + + public void addCredit(MessageCreditUnit unit, long value) + { + FlowCreditManager_0_10 creditManager = getCreditManager(); + + switch (unit) + { + case MESSAGE: + + creditManager.addCredit(value, 0L); + break; + case BYTE: + creditManager.addCredit(0l, value); + break; + } + + _stopped.set(false); + + if(creditManager.hasCredit()) + { + if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE)) + { + _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE); + } + } + + } + + public void setFlowMode(MessageFlowMode flowMode) + { + + + _creditManager.removeListener(this); + + switch(flowMode) + { + case CREDIT: + _creditManager = new CreditCreditManager(0l,0l); + break; + case WINDOW: + _creditManager = new WindowCreditManager(0l,0l); + break; + default: + throw new RuntimeException("Unknown message flow mode: " + flowMode); + } + _flowMode = flowMode; + if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED)) + { + _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED); + } + + _creditManager.addStateListener(this); + + } + + public boolean isStopped() + { + return _stopped.get(); + } + + public boolean acquires() + { + return _acquireMode == MessageAcquireMode.PRE_ACQUIRED; + } + + public void acknowledge(QueueEntry entry) + { + // TODO Fix Store Context / cleanup + if(entry.isAcquiredBy(this)) + { + _unacknowledgedBytes.addAndGet(-entry.getSize()); + _unacknowledgedCount.decrementAndGet(); + entry.discard(); + } + } + + public void flush() throws AMQException + { + flushCreditState(true); + _queue.flushSubscription(this); + stop(); + } + + public long getSubscriptionID() + { + return _subscriptionID; + } + + public LogActor getLogActor() + { + return _logActor; + } + + public boolean isTransient() + { + return false; + } + + public ServerSession getSessionModel() + { + return _session; + } + + public boolean isBrowsing() + { + return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; + } + + public boolean isExclusive() + { + return getQueue().hasExclusiveSubscriber(); + } + + public boolean isDurable() + { + return false; + } + + + public boolean isExplicitAcknowledge() + { + return _acceptMode == MessageAcceptMode.EXPLICIT; + } + + public String getCreditMode() + { + return _flowMode.toString(); + } + + public String getName() + { + return _destination; + } + + public Map getArguments() + { + return _arguments; + } + + public boolean isSessionTransactional() + { + return _session.isTransactional(); + } + + public void queueEmpty() + { + } + + public long getCreateTime() + { + return _createTime; + } + + public String toLogString() + { + String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(), + _queue.getNameShortString()); + String result = "[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getSubscriptionID()) + "(" + // queueString is "vh(/{0})/qu({1}) " so need to trim + + queueInfo.substring(0, queueInfo.length() - 1) + ")" + "] "; + return result; + } + + private String getFilterLogString() + { + StringBuilder filterLogString = new StringBuilder(); + String delimiter = ", "; + boolean hasEntries = false; + if (_filters != null && _filters.hasFilters()) + { + filterLogString.append(_filters.toString()); + hasEntries = true; + } + + if (isBrowser()) + { + if (hasEntries) + { + filterLogString.append(delimiter); + } + filterLogString.append("Browser"); + hasEntries = true; + } + + if (isDurable()) + { + if (hasEntries) + { + filterLogString.append(delimiter); + } + filterLogString.append("Durable"); + hasEntries = true; + } + + return filterLogString.toString(); + } + + public LogSubject getLogSubject() + { + return (LogSubject) this; + } + + + public void flushBatched() + { + _session.getConnection().flush(); + } + + public long getBytesOut() + { + return _deliveredBytes.longValue(); + } + + public long getMessagesOut() + { + return _deliveredCount.longValue(); + } + + public long getUnacknowledgedBytes() + { + return _unacknowledgedBytes.longValue(); + } + + public long getUnacknowledgedMessages() + { + return _unacknowledgedCount.longValue(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java new file mode 100644 index 0000000000..0c04f22232 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java @@ -0,0 +1,41 @@ +/* + * + * 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.v0_10; + +import org.apache.qpid.server.message.MessageReference; + +public class TransferMessageReference extends MessageReference +{ + public TransferMessageReference(MessageTransferMessage message) + { + super(message); + } + + protected void onReference(MessageTransferMessage message) + { + message.incrementReference(); + } + + protected void onRelease(MessageTransferMessage message) + { + message.decrementReference(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java new file mode 100644 index 0000000000..8e48741b91 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.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.server.protocol.v0_10; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.flow.AbstractFlowCreditManager; + +public class WindowCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 +{ + private static final Logger LOGGER = Logger.getLogger(WindowCreditManager.class); + + private volatile long _bytesCreditLimit; + private volatile long _messageCreditLimit; + + private volatile long _bytesUsed; + private volatile long _messageUsed; + + public WindowCreditManager() + { + this(0L, 0L); + } + + public WindowCreditManager(long bytesCreditLimit, long messageCreditLimit) + { + _bytesCreditLimit = bytesCreditLimit; + _messageCreditLimit = messageCreditLimit; + setSuspended(!hasCredit()); + + } + + public long getBytesCreditLimit() + { + return _bytesCreditLimit; + } + + public long getMessageCreditLimit() + { + return _messageCreditLimit; + } + + public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit) + { + _bytesCreditLimit = bytesCreditLimit; + _messageCreditLimit = messageCreditLimit; + + setSuspended(!hasCredit()); + + } + + + public long getMessageCredit() + { + return _messageCreditLimit == -1L + ? Long.MAX_VALUE + : _messageUsed < _messageCreditLimit ? _messageCreditLimit - _messageUsed : 0L; + } + + public long getBytesCredit() + { + return _bytesCreditLimit == -1L + ? Long.MAX_VALUE + : _bytesUsed < _bytesCreditLimit ? _bytesCreditLimit - _bytesUsed : 0L; + } + + public synchronized void restoreCredit(final long messageCredit, final long bytesCredit) + { + _messageUsed -= messageCredit; + if(_messageUsed < 0L) + { + LOGGER.error("Message credit used value was negative: "+ _messageUsed); + _messageUsed = 0; + } + + boolean notifyIncrease = true; + + if(_messageCreditLimit > 0L) + { + notifyIncrease = (_messageUsed != _messageCreditLimit); + } + + _bytesUsed -= bytesCredit; + if(_bytesUsed < 0L) + { + LOGGER.error("Bytes credit used value was negative: "+ _messageUsed); + _bytesUsed = 0; + } + + if(_bytesCreditLimit > 0L) + { + notifyIncrease = notifyIncrease && bytesCredit>0; + + if(notifyIncrease) + { + notifyIncreaseBytesCredit(); + } + } + + setSuspended(!hasCredit()); + } + + + + public synchronized boolean hasCredit() + { + return (_bytesCreditLimit < 0L || _bytesCreditLimit > _bytesUsed) + && (_messageCreditLimit < 0L || _messageCreditLimit > _messageUsed); + } + + public synchronized boolean useCreditForMessage(final long msgSize) + { + if(_messageCreditLimit >= 0L) + { + if(_messageUsed < _messageCreditLimit) + { + if(_bytesCreditLimit < 0L) + { + _messageUsed++; + + return true; + } + else if(_bytesUsed + msgSize <= _bytesCreditLimit) + { + _messageUsed++; + _bytesUsed += msgSize; + + return true; + } + else + { + return false; + } + } + else + { + setSuspended(true); + return false; + } + } + else if(_bytesCreditLimit >= 0L) + { + if(_bytesUsed + msgSize <= _bytesCreditLimit) + { + _bytesUsed += msgSize; + + return true; + } + else + { + return false; + } + + } + else + { + return true; + } + + } + + + public synchronized void addCredit(long count, long bytes) + { + if(bytes > 0) + { + _bytesCreditLimit += bytes; + } + else if(bytes == -1) + { + _bytesCreditLimit = -1; + } + + + if(count > 0) + { + _messageCreditLimit += count; + } + else if(count == -1) + { + _messageCreditLimit = -1; + } + } + + public void clearCredit() + { + _bytesCreditLimit = 0l; + _messageCreditLimit = 0l; + setSuspended(true); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java new file mode 100644 index 0000000000..6dac83a13f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -0,0 +1,1635 @@ +/* + * + * 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.v0_8; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; + +import org.apache.log4j.Logger; +import org.apache.qpid.AMQConnectionException; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.abstraction.ContentChunk; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.TransactionTimeoutHelper; +import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.flow.Pre0_10CreditManager; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogMessage; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.AMQPChannelActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ChannelMessages; +import org.apache.qpid.server.logging.messages.ExchangeMessages; +import org.apache.qpid.server.logging.subjects.ChannelLogSubject; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.InboundMessageAdapter; +import org.apache.qpid.server.queue.IncomingMessage; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +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.txn.AsyncAutoCommitTransaction; +import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.LocalTransaction.ActivityTimeAccessor; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.TransportException; + +public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.FutureRecorder +{ + public static final int DEFAULT_PREFETCH = 4096; + + private static final Logger _logger = Logger.getLogger(AMQChannel.class); + + //TODO use Broker property to configure message authorization requirements + private boolean _messageAuthorizationRequired = Boolean.getBoolean(BrokerProperties.PROPERTY_MSG_AUTH); + + private final int _channelId; + + + 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 + * value of this represents the last tag sent out + */ + private long _deliveryTag = 0; + + /** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */ + private AMQQueue _defaultQueue; + + /** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */ + private int _consumerTag; + + /** + * The current message - which may be partial in the sense that not all frames have been received yet - which has + * 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 IncomingMessage _currentMessage; + + /** Maps from consumer tag to subscription instance. Allows us to unsubscribe from a queue. */ + private final Map _tag2SubscriptionMap = new HashMap(); + + private final MessageStore _messageStore; + + private final LinkedList _unfinishedCommandsQueue = new LinkedList(); + + private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH); + + // Set of messages being acknowledged in the current transaction + private SortedSet _acknowledgedMessages = new TreeSet(); + + private final AtomicBoolean _suspended = new AtomicBoolean(false); + + private ServerTransaction _transaction; + + private final AtomicLong _txnStarts = new AtomicLong(0); + private final AtomicLong _txnCommits = new AtomicLong(0); + private final AtomicLong _txnRejects = new AtomicLong(0); + private final AtomicLong _txnCount = new AtomicLong(0); + + private final AMQProtocolSession _session; + private AtomicBoolean _closing = new AtomicBoolean(false); + + private final Set _blockingEntities = Collections.synchronizedSet(new HashSet()); + + private final AtomicBoolean _blocking = new AtomicBoolean(false); + + + private LogActor _actor; + private LogSubject _logSubject; + private volatile boolean _rollingBack; + + private static final Runnable NULL_TASK = new Runnable() { public void run() {} }; + private List _resendList = new ArrayList(); + private static final + AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); + private long _createTime = System.currentTimeMillis(); + + private final ClientDeliveryMethod _clientDeliveryMethod; + + private final TransactionTimeoutHelper _transactionTimeoutHelper; + private final UUID _id = UUID.randomUUID(); + + public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) + throws AMQException + { + _session = session; + _channelId = channelId; + + _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); + _logSubject = new ChannelLogSubject(this); + _actor.message(ChannelMessages.CREATE()); + + _messageStore = messageStore; + + // by default the session is non-transactional + _transaction = new AsyncAutoCommitTransaction(_messageStore, this); + + _clientDeliveryMethod = session.createDeliveryMethod(_channelId); + + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() + { + @Override + public void doTimeoutAction(String reason) throws AMQException + { + closeConnection(reason); + } + }); + } + + /** Sets this channel to be part of a local transaction */ + public void setLocalTransactional() + { + _transaction = new LocalTransaction(_messageStore, new ActivityTimeAccessor() + { + @Override + public long getActivityTime() + { + return _session.getLastReceivedTime(); + } + }); + _txnStarts.incrementAndGet(); + } + + public boolean isTransactional() + { + return _transaction.isTransactional(); + } + + public void receivedComplete() + { + sync(); + } + + private void incrementOutstandingTxnsIfNecessary() + { + if(isTransactional()) + { + //There can currently only be at most one outstanding transaction + //due to only having LocalTransaction support. Set value to 1 if 0. + _txnCount.compareAndSet(0,1); + } + } + + private void decrementOutstandingTxnsIfNecessary() + { + if(isTransactional()) + { + //There can currently only be at most one outstanding transaction + //due to only having LocalTransaction support. Set value to 0 if 1. + _txnCount.compareAndSet(1,0); + } + } + + public Long getTxnCommits() + { + return _txnCommits.get(); + } + + public Long getTxnRejects() + { + return _txnRejects.get(); + } + + public Long getTxnCount() + { + return _txnCount.get(); + } + + public Long getTxnStart() + { + return _txnStarts.get(); + } + + public int getChannelId() + { + return _channelId; + } + + public void setPublishFrame(MessagePublishInfo info, final Exchange e) throws AMQSecurityException + { + String routingKey = info.getRoutingKey() == null ? null : info.getRoutingKey().asString(); + SecurityManager securityManager = getVirtualHost().getSecurityManager(); + if (!securityManager.authorisePublish(info.isImmediate(), routingKey, e.getName())) + { + throw new AMQSecurityException("Permission denied: " + e.getName()); + } + _currentMessage = new IncomingMessage(info, getProtocolSession().getReference()); + _currentMessage.setExchange(e); + } + + public void publishContentHeader(ContentHeaderBody contentHeaderBody) + throws AMQException + { + if (_currentMessage == null) + { + throw new AMQException("Received content header without previously receiving a BasicPublish frame"); + } + else + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Content header received on channel " + _channelId); + } + + _currentMessage.setContentHeaderBody(contentHeaderBody); + + _currentMessage.setExpiration(); + + _currentMessage.headersReceived(getProtocolSession().getLastReceivedTime()); + + _currentMessage.route(); + + deliverCurrentMessageIfComplete(); + } + } + + private void deliverCurrentMessageIfComplete() + throws AMQException + { + // check and deliver if header says body length is zero + if (_currentMessage.allContentReceived()) + { + try + { + final List destinationQueues = _currentMessage.getDestinationQueues(); + + if(!checkMessageUserId(_currentMessage.getContentHeader())) + { + _transaction.addPostTransactionAction(new WriteReturnAction(AMQConstant.ACCESS_REFUSED, "Access Refused", _currentMessage)); + } + else + { + if(destinationQueues == null || destinationQueues.isEmpty()) + { + handleUnroutableMessage(); + } + else + { + final StoredMessage handle = _messageStore.addMessage(_currentMessage.getMessageMetaData()); + _currentMessage.setStoredMessage(handle); + int bodyCount = _currentMessage.getBodyCount(); + if(bodyCount > 0) + { + long bodyLengthReceived = 0; + for(int i = 0 ; i < bodyCount ; i++) + { + ContentChunk contentChunk = _currentMessage.getContentChunk(i); + handle.addContent((int)bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData())); + bodyLengthReceived += contentChunk.getSize(); + } + } + + _transaction.addPostTransactionAction(new ServerTransaction.Action() + { + public void postCommit() + { + } + + public void onRollback() + { + handle.remove(); + } + }); + + _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues)); + incrementOutstandingTxnsIfNecessary(); + _currentMessage.getStoredMessage().flushToStore(); + } + } + } + finally + { + long bodySize = _currentMessage.getSize(); + long timestamp = ((BasicContentHeaderProperties) _currentMessage.getContentHeader().getProperties()).getTimestamp(); + _session.registerMessageReceived(bodySize, timestamp); + _currentMessage = null; + } + } + + } + + /** + * Either throws a {@link AMQConnectionException} or returns the message + * + * Pre-requisite: the current message is judged to have no destination queues. + * + * @throws AMQConnectionException if the message is mandatoryclose-on-no-route + * @see AMQProtocolSession#isCloseWhenNoRoute() + */ + private void handleUnroutableMessage() throws AMQConnectionException + { + boolean mandatory = _currentMessage.isMandatory(); + String description = currentMessageDescription(); + boolean closeOnNoRoute = _session.isCloseWhenNoRoute(); + + if(_logger.isDebugEnabled()) + { + _logger.debug(String.format( + "Unroutable message %s, mandatory=%s, transactionalSession=%s, closeOnNoRoute=%s", + description, mandatory, isTransactional(), closeOnNoRoute)); + } + + if (mandatory && isTransactional() && _session.isCloseWhenNoRoute()) + { + throw new AMQConnectionException( + AMQConstant.NO_ROUTE, + "No route for message " + currentMessageDescription(), + 0, 0, // default class and method ids + getProtocolSession().getProtocolVersion().getMajorVersion(), + getProtocolSession().getProtocolVersion().getMinorVersion(), + (Throwable) null); + } + + if (mandatory || _currentMessage.isImmediate()) + { + _transaction.addPostTransactionAction(new WriteReturnAction(AMQConstant.NO_ROUTE, "No Route for message " + currentMessageDescription(), _currentMessage)); + } + else + { + _actor.message(ExchangeMessages.DISCARDMSG(_currentMessage.getExchange().asString(), _currentMessage.getRoutingKey())); + } + } + + private String currentMessageDescription() + { + if(_currentMessage == null || !_currentMessage.allContentReceived()) + { + throw new IllegalStateException("Cannot create message description for message: " + _currentMessage); + } + + return String.format( + "[Exchange: %s, Routing key: %s]", + _currentMessage.getExchange(), + _currentMessage.getRoutingKey()); + } + + public void publishContentBody(ContentBody contentBody) throws AMQException + { + if (_currentMessage == null) + { + throw new AMQException("Received content body without previously receiving a JmsPublishBody"); + } + + if (_logger.isDebugEnabled()) + { + _logger.debug(debugIdentity() + " content body received on channel " + _channelId); + } + + try + { + final ContentChunk contentChunk = + _session.getMethodRegistry().getProtocolVersionMethodConverter().convertToContentChunk(contentBody); + + _currentMessage.addContentBodyFrame(contentChunk); + + deliverCurrentMessageIfComplete(); + } + catch (AMQException e) + { + // we want to make sure we don't keep a reference to the message in the + // event of an error + _currentMessage = null; + throw e; + } + catch (RuntimeException e) + { + // we want to make sure we don't keep a reference to the message in the + // event of an error + _currentMessage = null; + throw e; + } + } + + public long getNextDeliveryTag() + { + return ++_deliveryTag; + } + + public int getNextConsumerTag() + { + return ++_consumerTag; + } + + + public Subscription getSubscription(AMQShortString subscription) + { + return _tag2SubscriptionMap.get(subscription); + } + + /** + * Subscribe to a queue. We register all subscriptions in the channel so that if the channel is closed we can clean + * up all subscriptions, even if the client does not explicitly unsubscribe from all queues. + * + * @param tag the tag chosen by the client (if null, server will generate one) + * @param queue the queue to subscribe to + * @param acks Are acks enabled for this subscriber + * @param filters Filters to apply to this subscriber + * + * @param noLocal Flag stopping own messages being received. + * @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 AMQException if something goes wrong + */ + public AMQShortString subscribeToQueue(AMQShortString tag, AMQQueue queue, boolean acks, + FieldTable filters, boolean noLocal, boolean exclusive) throws AMQException + { + if (tag == null) + { + tag = new AMQShortString("sgen_" + getNextConsumerTag()); + } + + if (_tag2SubscriptionMap.containsKey(tag)) + { + throw new AMQException("Consumer already exists with same tag: " + tag); + } + + 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. + + _tag2SubscriptionMap.put(tag, subscription); + + try + { + queue.registerSubscription(subscription, exclusive); + } + catch (AMQException e) + { + _tag2SubscriptionMap.remove(tag); + throw e; + } + catch (RuntimeException e) + { + _tag2SubscriptionMap.remove(tag); + throw e; + } + return tag; + } + + /** + * Unsubscribe a consumer from a queue. + * @param consumerTag + * @return true if the consumerTag had a mapped queue that could be unregistered. + * @throws AMQException + */ + public boolean unsubscribeConsumer(AMQShortString consumerTag) throws AMQException + { + + Subscription sub = _tag2SubscriptionMap.remove(consumerTag); + if (sub != null) + { + try + { + sub.getSendLock(); + sub.getQueue().unregisterSubscription(sub); + } + finally + { + sub.releaseSendLock(); + } + return true; + } + else + { + _logger.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 + * + * @throws AMQException if there is an error during closure + */ + @Override + public void close() throws AMQException + { + close(null, null); + } + + public void close(AMQConstant cause, String message) throws AMQException + { + if(!_closing.compareAndSet(false, true)) + { + //Channel is already closing + return; + } + + LogMessage operationalLogMessage = cause == null ? + ChannelMessages.CLOSE() : + ChannelMessages.CLOSE_FORCED(cause.getCode(), message); + CurrentActor.get().message(_logSubject, operationalLogMessage); + + unsubscribeAllConsumers(); + _transaction.rollback(); + + try + { + requeue(); + } + catch (AMQException e) + { + _logger.error("Caught AMQException whilst attempting to requeue:" + e); + } + catch (TransportException e) + { + _logger.error("Caught TransportException whilst attempting to requeue:" + e); + } + } + + private void unsubscribeAllConsumers() throws AMQException + { + if (_logger.isInfoEnabled()) + { + if (!_tag2SubscriptionMap.isEmpty()) + { + _logger.info("Unsubscribing all consumers on channel " + toString()); + } + else + { + _logger.info("No consumers to unsubscribe on channel " + toString()); + } + } + + for (Map.Entry me : _tag2SubscriptionMap.entrySet()) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Unsubscribing consumer '" + me.getKey() + "' on channel " + toString()); + } + + Subscription sub = me.getValue(); + + try + { + sub.getSendLock(); + sub.getQueue().unregisterSubscription(sub); + } + finally + { + sub.releaseSendLock(); + } + + } + + _tag2SubscriptionMap.clear(); + } + + /** + * Add a message to the channel-based list of unacknowledged messages + * + * @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 subscription The consumer that is to acknowledge this message. + */ + public void addUnacknowledgedMessage(QueueEntry entry, long deliveryTag, Subscription subscription) + { + if (_logger.isDebugEnabled()) + { + if (entry.getQueue() == null) + { + _logger.debug("Adding unacked message with a null queue:" + entry); + } + else + { + if (_logger.isDebugEnabled()) + { + _logger.debug(debugIdentity() + " Adding unacked message(" + entry.getMessage().toString() + " DT:" + deliveryTag + + ") with a queue(" + entry.getQueue() + ") for " + subscription); + } + } + } + + _unacknowledgedMessageMap.add(deliveryTag, entry); + + } + + private final String id = "(" + System.identityHashCode(this) + ")"; + + public String debugIdentity() + { + return _channelId + id; + } + + /** + * Called to attempt re-delivery all outstanding unacknowledged messages on the channel. May result in delivery to + * this same channel or to other subscribers. + * + * @throws org.apache.qpid.AMQException if the requeue fails + */ + 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 messagesToBeDelivered = _unacknowledgedMessageMap.cancelAllMessages(); + + if (!messagesToBeDelivered.isEmpty()) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Requeuing " + messagesToBeDelivered.size() + " unacked messages. for " + toString()); + } + + } + + for (QueueEntry unacked : messagesToBeDelivered) + { + if (!unacked.isQueueDeleted()) + { + // Mark message redelivered + unacked.setRedelivered(); + + // Ensure message is released for redelivery + unacked.release(); + + } + else + { + unacked.discard(); + } + } + + } + + /** + * Requeue a single message + * + * @param deliveryTag The message to requeue + * + * @throws AMQException If something goes wrong. + */ + public void requeue(long deliveryTag) throws AMQException + { + QueueEntry unacked = _unacknowledgedMessageMap.remove(deliveryTag); + + if (unacked != null) + { + // Mark message redelivered + unacked.setRedelivered(); + + // Ensure message is released for redelivery + if (!unacked.isQueueDeleted()) + { + + // Ensure message is released for redelivery + unacked.release(); + + } + else + { + _logger.warn(System.identityHashCode(this) + " Requested requeue of message(" + unacked + + "):" + deliveryTag + " but no queue defined and no DeadLetter queue so DROPPING message."); + + unacked.discard(); + } + } + else + { + _logger.warn("Requested requeue of message:" + deliveryTag + " but no such delivery tag exists." + + _unacknowledgedMessageMap.size()); + + } + + } + + public boolean isMaxDeliveryCountEnabled(final long deliveryTag) + { + final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag); + if (queueEntry != null) + { + final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount(); + return maximumDeliveryCount > 0; + } + + return false; + } + + public boolean isDeliveredTooManyTimes(final long deliveryTag) + { + final QueueEntry queueEntry = _unacknowledgedMessageMap.get(deliveryTag); + if (queueEntry != null) + { + final int maximumDeliveryCount = queueEntry.getQueue().getMaximumDeliveryCount(); + final int numDeliveries = queueEntry.getDeliveryCount(); + return maximumDeliveryCount != 0 && numDeliveries >= maximumDeliveryCount; + } + + return false; + } + + /** + * Called to resend all outstanding unacknowledged messages to this same channel. + * + * @param requeue Are the messages to be requeued or dropped. + * + * @throws AMQException When something goes wrong. + */ + public void resend(final boolean requeue) throws AMQException + { + + + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + if (_logger.isDebugEnabled()) + { + _logger.debug("unacked map Size:" + _unacknowledgedMessageMap.size()); + } + + // 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 ExtractResendAndRequeue(_unacknowledgedMessageMap, + msgToRequeue, + msgToResend, + requeue, + _messageStore)); + + + // Process Messages to Resend + if (_logger.isDebugEnabled()) + { + if (!msgToResend.isEmpty()) + { + _logger.debug("Preparing (" + msgToResend.size() + ") message to resend."); + } + else + { + _logger.debug("No message to resend."); + } + } + + for (Map.Entry entry : msgToResend.entrySet()) + { + QueueEntry message = entry.getValue(); + long deliveryTag = entry.getKey(); + + //Amend the delivery counter as the client hasn't seen these messages yet. + message.decrementDeliveryCount(); + + AMQQueue queue = message.getQueue(); + + // Without any details from the client about what has been processed we have to mark + // all messages in the unacked map as redelivered. + message.setRedelivered(); + + Subscription sub = message.getDeliveredSubscription(); + + if (sub != null) + { + + if(!queue.resend(message,sub)) + { + msgToRequeue.put(deliveryTag, message); + } + } + else + { + + if (_logger.isInfoEnabled()) + { + _logger.info("DeliveredSubscription not recorded so just requeueing(" + message.toString() + + ")to prevent loss"); + } + // move this message to requeue + msgToRequeue.put(deliveryTag, message); + } + } // for all messages + // } else !isSuspend + + if (_logger.isInfoEnabled()) + { + if (!msgToRequeue.isEmpty()) + { + _logger.info("Preparing (" + msgToRequeue.size() + ") message to requeue to."); + } + } + + // Process Messages to Requeue at the front of the queue + for (Map.Entry entry : msgToRequeue.entrySet()) + { + QueueEntry message = entry.getValue(); + long deliveryTag = entry.getKey(); + + //Amend the delivery counter as the client hasn't seen these messages yet. + message.decrementDeliveryCount(); + + _unacknowledgedMessageMap.remove(deliveryTag); + + message.setRedelivered(); + message.release(); + + } + } + + + /** + * Acknowledge one or more messages. + * + * @param deliveryTag the last delivery tag + * @param multiple if true will acknowledge all messages up to an including the delivery tag. if false only + * acknowledges the single message specified by the delivery tag + * + * @throws AMQException if the delivery tag is unknown (e.g. not outstanding) on this channel + */ + public void acknowledgeMessage(long deliveryTag, boolean multiple) throws AMQException + { + Collection ackedMessages = getAckedMessages(deliveryTag, multiple); + _transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages)); + } + + private Collection getAckedMessages(long deliveryTag, boolean multiple) + { + + return _unacknowledgedMessageMap.acknowledge(deliveryTag, multiple); + + } + + /** + * Used only for testing purposes. + * + * @return the map of unacknowledged messages + */ + public UnacknowledgedMessageMap getUnacknowledgedMessageMap() + { + return _unacknowledgedMessageMap; + } + + /** + * Called from the ChannelFlowHandler to suspend this Channel + * @param suspended boolean, should this Channel be suspended + */ + public void setSuspended(boolean suspended) + { + boolean wasSuspended = _suspended.getAndSet(suspended); + if (wasSuspended != suspended) + { + // Log Flow Started before we start the subscriptions + if (!suspended) + { + _actor.message(_logSubject, ChannelMessages.FLOW("Started")); + } + + + // This section takes two different approaches to perform to perform + // the same function. Ensuring that the Subscription has taken note + // of the change in Channel State + + // Here we have become unsuspended and so we ask each the queue to + // perform an Async delivery for each of the subscriptions in this + // Channel. The alternative would be to ensure that the subscription + // had received the change in suspension state. That way the logic + // behind decieding to start an async delivery was located with the + // Subscription. + if (wasSuspended) + { + // may need to deliver queued messages + for (Subscription s : _tag2SubscriptionMap.values()) + { + s.getQueue().deliverAsync(s); + } + } + + + // Here we have become suspended so we need to ensure that each of + // the Subscriptions has noticed this change so that we can be sure + // they are not still sending messages. Again the code here is a + // very simplistic approach to ensure that the change of suspension + // has been noticed by each of the Subscriptions. Unlike the above + // case we don't actually need to do anything else. + if (!wasSuspended) + { + // may need to deliver queued messages + for (Subscription s : _tag2SubscriptionMap.values()) + { + try + { + s.getSendLock(); + } + finally + { + s.releaseSendLock(); + } + } + } + + + // Log Suspension only after we have confirmed all suspensions are + // stopped. + if (suspended) + { + _actor.message(_logSubject, ChannelMessages.FLOW("Stopped")); + } + + } + } + + public boolean isSuspended() + { + return _suspended.get() || _closing.get() || _session.isClosing(); + } + + public void commit() throws AMQException + { + commit(null, false); + } + + + public void commit(final Runnable immediateAction, boolean async) throws AMQException + { + + if (!isTransactional()) + { + throw new AMQException("Fatal error: commit called on non-transactional channel"); + } + + if(async && _transaction instanceof LocalTransaction) + { + + ((LocalTransaction)_transaction).commitAsync(new Runnable() + { + @Override + public void run() + { + immediateAction.run(); + _txnCommits.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + }); + } + else + { + _transaction.commit(immediateAction); + + _txnCommits.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + } + + public void rollback() throws AMQException + { + rollback(NULL_TASK); + } + + public void rollback(Runnable postRollbackTask) throws AMQException + { + if (!isTransactional()) + { + throw new AMQException("Fatal error: commit called on non-transactional channel"); + } + + // stop all subscriptions + _rollingBack = true; + boolean requiresSuspend = _suspended.compareAndSet(false,true); + + // ensure all subscriptions have seen the change to the channel state + for(Subscription sub : _tag2SubscriptionMap.values()) + { + sub.getSendLock(); + sub.releaseSendLock(); + } + + try + { + _transaction.rollback(); + } + finally + { + _rollingBack = false; + + _txnRejects.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + + postRollbackTask.run(); + + for(QueueEntry entry : _resendList) + { + Subscription sub = entry.getDeliveredSubscription(); + if(sub == null || sub.isClosed()) + { + entry.release(); + } + else + { + sub.getQueue().resend(entry, sub); + } + } + _resendList.clear(); + + if(requiresSuspend) + { + _suspended.set(false); + for(Subscription sub : _tag2SubscriptionMap.values()) + { + sub.getQueue().deliverAsync(sub); + } + + } + } + + public String toString() + { + return "["+_session.toString()+":"+_channelId+"]"; + } + + public void setDefaultQueue(AMQQueue queue) + { + _defaultQueue = queue; + } + + public AMQQueue getDefaultQueue() + { + return _defaultQueue; + } + + + public boolean isClosing() + { + return _closing.get(); + } + + public AMQProtocolSession getProtocolSession() + { + return _session; + } + + public FlowCreditManager getCreditManager() + { + return _creditManager; + } + + public void setCredit(final long prefetchSize, final int prefetchCount) + { + _actor.message(ChannelMessages.PREFETCH_SIZE(prefetchSize, prefetchCount)); + _creditManager.setCreditLimits(prefetchSize, prefetchCount); + } + + public MessageStore getMessageStore() + { + return _messageStore; + } + + 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; + } + + + private AMQMessage createAMQMessage(IncomingMessage incomingMessage) + throws AMQException + { + + AMQMessage message = new AMQMessage(incomingMessage.getStoredMessage()); + + message.setExpiration(incomingMessage.getExpiration()); + message.setConnectionIdentifier(_session.getReference()); + return message; + } + + private boolean checkMessageUserId(ContentHeaderBody header) + { + AMQShortString userID = + header.getProperties() instanceof BasicContentHeaderProperties + ? ((BasicContentHeaderProperties) header.getProperties()).getUserId() + : null; + + return (!_messageAuthorizationRequired || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString())); + + } + + @Override + public UUID getId() + { + return _id; + } + + public AMQConnectionModel getConnectionModel() + { + return _session; + } + + public String getClientID() + { + return String.valueOf(_session.getContextKey()); + } + + public LogSubject getLogSubject() + { + return _logSubject; + } + + @Override + public int compareTo(AMQSessionModel o) + { + return getId().compareTo(o.getId()); + } + + private class MessageDeliveryAction implements ServerTransaction.Action + { + private IncomingMessage _incommingMessage; + private List _destinationQueues; + + public MessageDeliveryAction(IncomingMessage currentMessage, + List destinationQueues) + { + _incommingMessage = currentMessage; + _destinationQueues = destinationQueues; + } + + public void postCommit() + { + try + { + final boolean immediate = _incommingMessage.isImmediate(); + + final AMQMessage amqMessage = createAMQMessage(_incommingMessage); + MessageReference ref = amqMessage.newReference(); + + for(int i = 0; i < _destinationQueues.size(); i++) + { + BaseQueue queue = _destinationQueues.get(i); + + BaseQueue.PostEnqueueAction action; + + if(immediate) + { + action = new ImmediateAction(queue); + } + else + { + action = null; + } + + queue.enqueue(amqMessage, isTransactional(), action); + + if(queue instanceof AMQQueue) + { + ((AMQQueue)queue).checkCapacity(AMQChannel.this); + } + + } + + _incommingMessage.getStoredMessage().flushToStore(); + ref.release(); + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + } + + public void onRollback() + { + // Maybe keep track of entries that were created and then delete them here in case of failure + // to in memory enqueue + } + + private class ImmediateAction implements BaseQueue.PostEnqueueAction + { + private final BaseQueue _queue; + + public ImmediateAction(BaseQueue queue) + { + _queue = queue; + } + + public void onEnqueue(QueueEntry entry) + { + if (!entry.getDeliveredToConsumer() && entry.acquire()) + { + + + ServerTransaction txn = new LocalTransaction(_messageStore); + Collection entries = new ArrayList(1); + entries.add(entry); + final AMQMessage message = (AMQMessage) entry.getMessage(); + txn.dequeue(_queue, entry.getMessage(), + new MessageAcknowledgeAction(entries) + { + @Override + public void postCommit() + { + try + { + final + ProtocolOutputConverter outputConverter = + _session.getProtocolOutputConverter(); + + outputConverter.writeReturn(message.getMessagePublishInfo(), + message.getContentHeaderBody(), + message, + _channelId, + AMQConstant.NO_CONSUMERS.getCode(), + IMMEDIATE_DELIVERY_REPLY_TEXT); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + super.postCommit(); + } + } + ); + txn.commit(); + + + } + + } + } + } + + private class MessageAcknowledgeAction implements ServerTransaction.Action + { + private final Collection _ackedMessages; + + public MessageAcknowledgeAction(Collection ackedMessages) + { + _ackedMessages = ackedMessages; + } + + public void postCommit() + { + try + { + for(QueueEntry entry : _ackedMessages) + { + entry.discard(); + } + } + finally + { + _acknowledgedMessages.clear(); + } + + } + + public void onRollback() + { + // explicit rollbacks resend the message after the rollback-ok is sent + if(_rollingBack) + { + _resendList.addAll(_ackedMessages); + } + else + { + try + { + for(QueueEntry entry : _ackedMessages) + { + entry.release(); + } + } + finally + { + _acknowledgedMessages.clear(); + } + } + + } + } + + private class WriteReturnAction implements ServerTransaction.Action + { + private final AMQConstant _errorCode; + private final IncomingMessage _message; + private final String _description; + + public WriteReturnAction(AMQConstant errorCode, + String description, + IncomingMessage message) + { + _errorCode = errorCode; + _message = message; + _description = description; + } + + public void postCommit() + { + try + { + _session.getProtocolOutputConverter().writeReturn(_message.getMessagePublishInfo(), + _message.getContentHeader(), + _message, + _channelId, + _errorCode.getCode(), + AMQShortString.valueOf(_description, true, true)); + } + catch (AMQException e) + { + //TODO + throw new RuntimeException(e); + } + + } + + public void onRollback() + { + } + } + + + public LogActor getLogActor() + { + return _actor; + } + + public synchronized void block() + { + if(_blockingEntities.add(this)) + { + if(_blocking.compareAndSet(false,true)) + { + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED("** All Queues **")); + flow(false); + } + } + } + + public synchronized void unblock() + { + if(_blockingEntities.remove(this)) + { + if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false)) + { + _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); + + flow(true); + } + } + } + + public synchronized void block(AMQQueue queue) + { + if(_blockingEntities.add(queue)) + { + + if(_blocking.compareAndSet(false,true)) + { + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getNameShortString().toString())); + flow(false); + } + } + } + + public synchronized void unblock(AMQQueue queue) + { + if(_blockingEntities.remove(queue)) + { + if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false) && !isClosing()) + { + _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); + + flow(true); + } + } + } + + public boolean onSameConnection(InboundMessage inbound) + { + if(inbound instanceof IncomingMessage) + { + IncomingMessage incoming = (IncomingMessage) inbound; + return getProtocolSession().getReference() == incoming.getConnectionReference(); + } + return false; + } + + public int getUnacknowledgedMessageCount() + { + return getUnacknowledgedMessageMap().size(); + } + + private void flow(boolean flow) + { + MethodRegistry methodRegistry = _session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createChannelFlowBody(flow); + _session.writeFrame(responseBody.generateFrame(_channelId)); + } + + @Override + public boolean getBlocking() + { + return _blocking.get(); + } + + public VirtualHost getVirtualHost() + { + return getProtocolSession().getVirtualHost(); + } + + public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException + { + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); + } + + /** + * Typically called from the HouseKeepingThread instead of the main receiver thread, + * therefore uses a lock to close the connection in a thread-safe manner. + */ + private void closeConnection(String reason) throws AMQException + { + Lock receivedLock = _session.getReceivedLock(); + receivedLock.lock(); + try + { + _session.close(AMQConstant.RESOURCE_ERROR, reason); + } + finally + { + receivedLock.unlock(); + } + } + + public void deadLetter(long deliveryTag) throws AMQException + { + final UnacknowledgedMessageMap unackedMap = getUnacknowledgedMessageMap(); + final QueueEntry rejectedQueueEntry = unackedMap.get(deliveryTag); + + if (rejectedQueueEntry == null) + { + _logger.warn("No message found, unable to DLQ delivery tag: " + deliveryTag); + return; + } + else + { + final ServerMessage msg = rejectedQueueEntry.getMessage(); + + final AMQQueue queue = rejectedQueueEntry.getQueue(); + + final Exchange altExchange = queue.getAlternateExchange(); + unackedMap.remove(deliveryTag); + + if (altExchange == null) + { + _logger.debug("No alternate exchange configured for queue, must discard the message as unable to DLQ: delivery tag: " + deliveryTag); + _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), queue.getName(), msg.getRoutingKey())); + rejectedQueueEntry.discard(); + return; + } + + final InboundMessage m = new InboundMessageAdapter(rejectedQueueEntry); + + final List destinationQueues = altExchange.route(m); + + if (destinationQueues == null || destinationQueues.isEmpty()) + { + _logger.debug("Routing process provided no queues to enqueue the message on, must discard message as unable to DLQ: delivery tag: " + deliveryTag); + _actor.message(_logSubject, ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), altExchange.getName())); + rejectedQueueEntry.discard(); + return; + } + + rejectedQueueEntry.routeToAlternate(); + + //output operational logging for each delivery post commit + for (final BaseQueue destinationQueue : destinationQueues) + { + _actor.message(_logSubject, ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); + } + + } + } + + public void recordFuture(final StoreFuture future, final ServerTransaction.Action action) + { + _unfinishedCommandsQueue.add(new AsyncCommand(future, action)); + } + + public void sync() + { + if(_logger.isDebugEnabled()) + { + _logger.debug("sync() called on channel " + debugIdentity()); + } + + AsyncCommand cmd; + while((cmd = _unfinishedCommandsQueue.poll()) != null) + { + cmd.awaitReadyForCompletion(); + cmd.complete(); + } + if(_transaction instanceof LocalTransaction) + { + ((LocalTransaction)_transaction).sync(); + } + } + + private static class AsyncCommand + { + private final StoreFuture _future; + private ServerTransaction.Action _action; + + public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action) + { + _future = future; + _action = action; + } + + void awaitReadyForCompletion() + { + _future.waitForCompletion(); + } + + void complete() + { + if(!_future.isComplete()) + { + _future.waitForCompletion(); + } + _action.postCommit(); + _action = null; + } + } + + @Override + public int getConsumerCount() + { + return _tag2SubscriptionMap.size(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.java new file mode 100644 index 0000000000..3567a005d2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.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.server.protocol.v0_8; + +import org.apache.log4j.Logger; + +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.message.AMQMessageHeader; +import org.apache.qpid.server.message.AbstractServerMessageImpl; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.store.StoredMessage; + +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; + +/** + * A deliverable message. + */ +public class AMQMessage extends AbstractServerMessageImpl +{ + /** Used for debugging purposes. */ + private static final Logger _log = Logger.getLogger(AMQMessage.class); + + /** 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 static final byte DELIVERED_TO_CONSUMER = 0x02; + + private byte _flags = 0; + + private long _expiration; + + private final long _size; + + private Object _connectionIdentifier; + private static final byte IMMEDIATE_AND_DELIVERED = (byte) (IMMEDIATE | DELIVERED_TO_CONSUMER); + + public AMQMessage(StoredMessage handle) + { + this(handle, null); + } + + public AMQMessage(StoredMessage handle, WeakReference channelRef) + { + super(handle); + + + final MessageMetaData metaData = handle.getMetaData(); + _size = metaData.getContentSize(); + final MessagePublishInfo messagePublishInfo = metaData.getMessagePublishInfo(); + + if(messagePublishInfo.isImmediate()) + { + _flags |= IMMEDIATE; + } + } + + public void setExpiration(final long expiration) + { + + _expiration = expiration; + + } + + public MessageMetaData getMessageMetaData() + { + return getStoredMessage().getMetaData(); + } + + public ContentHeaderBody getContentHeaderBody() + { + return getMessageMetaData().getContentHeaderBody(); + } + + public Long getMessageId() + { + return getStoredMessage().getMessageNumber(); + } + + /** + * Called selectors to determin if the message has already been sent + * + * @return _deliveredToConsumer + */ + public boolean getDeliveredToConsumer() + { + return (_flags & DELIVERED_TO_CONSUMER) != 0; + } + + public String getRoutingKey() + { + MessageMetaData messageMetaData = getMessageMetaData(); + if (messageMetaData != null) + { + AMQShortString routingKey = messageMetaData.getMessagePublishInfo().getRoutingKey(); + if (routingKey != null) + { + return routingKey.asString(); + } + } + return null; + } + + public AMQMessageHeader getMessageHeader() + { + return getMessageMetaData().getMessageHeader(); + } + + public boolean isPersistent() + { + return getMessageMetaData().isPersistent(); + } + + /** + * Called to enforce the 'immediate' flag. + * + * @returns true if the message is marked for immediate delivery but has not been marked as delivered + * to a consumer + */ + public boolean immediateAndNotDelivered() + { + + return (_flags & IMMEDIATE_AND_DELIVERED) == IMMEDIATE; + + } + + public MessagePublishInfo getMessagePublishInfo() throws AMQException + { + return getMessageMetaData().getMessagePublishInfo(); + } + + public long getArrivalTime() + { + return getMessageMetaData().getArrivalTime(); + } + + /** + * Checks to see if the message has expired. If it has the message is dequeued. + * + * @param queue The queue to check the expiration against. (Currently not used) + * + * @return true if the message has expire + * + * @throws AMQException + */ + public boolean expired(AMQQueue queue) throws AMQException + { + + if (_expiration != 0L) + { + long now = System.currentTimeMillis(); + + return (now > _expiration); + } + + return false; + } + + /** + * Called when this message is delivered to a consumer. (used to implement the 'immediate' flag functionality). + * And for selector efficiency. + */ + public void setDeliveredToConsumer() + { + _flags |= DELIVERED_TO_CONSUMER; + } + + public long getSize() + { + return _size; + + } + + public boolean isImmediate() + { + return (_flags & IMMEDIATE) == IMMEDIATE; + } + + public long getExpiration() + { + return _expiration; + } + + public MessageReference newReference() + { + return new AMQMessageReference(this); + } + + public long getMessageNumber() + { + return getStoredMessage().getMessageNumber(); + } + + + public Object getConnectionIdentifier() + { + return _connectionIdentifier; + + } + + public void setConnectionIdentifier(final Object connectionIdentifier) + { + _connectionIdentifier = connectionIdentifier; + } + + + public String toString() + { + return "Message[" + debugIdentity() + "]: " + getMessageId() + "; ref count: " + getReferenceCount(); + } + + public int getContent(ByteBuffer buf, int offset) + { + return getStoredMessage().getContent(offset, buf); + } + + + public ByteBuffer getContent(int offset, int size) + { + return getStoredMessage().getContent(offset, size); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.java new file mode 100644 index 0000000000..3adc9f70cd --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.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.protocol.v0_8; + +import org.apache.qpid.server.message.MessageReference; + +public class AMQMessageReference extends MessageReference +{ + + + public AMQMessageReference(AMQMessage message) + { + super(message); + } + + protected void onReference(AMQMessage message) + { + message.incrementReference(); + } + + protected void onRelease(AMQMessage message) + { + message.decrementReference(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java new file mode 100644 index 0000000000..8faf1a7c65 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java @@ -0,0 +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.v0_8; + +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. + * + *

+ *
CRC Card
Responsibilities Collaborations + *
Represents failure to handle an AMQP method. + *
+ * + * @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 evt) + { + super("AMQMethodEvent " + evt + " was not processed by any listener on Broker."); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java new file mode 100644 index 0000000000..6de8486b56 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java @@ -0,0 +1,1686 @@ +/* + * + * 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.v0_8; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import javax.security.auth.Subject; +import javax.security.sasl.SaslServer; + +import org.apache.log4j.Logger; +import org.apache.qpid.AMQChannelException; +import org.apache.qpid.AMQConnectionException; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.codec.AMQCodecFactory; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.common.ServerPropertyNames; +import org.apache.qpid.framing.AMQBody; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQProtocolHeaderException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ChannelCloseBody; +import org.apache.qpid.framing.ChannelCloseOkBody; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.FieldTableFactory; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.MethodDispatcher; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolInitiation; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.properties.ConnectionStartProperties; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.protocol.AMQMethodEvent; +import org.apache.qpid.protocol.AMQMethodListener; +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.protocol.v0_8.handler.ServerMethodDispatcherImpl; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.AMQPConnectionActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.ManagementActor; +import org.apache.qpid.server.logging.messages.ConnectionMessages; +import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverterRegistry; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.stats.StatisticsCounter; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.util.BytesDataOutput; + +public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession +{ + private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); + + // to save boxing the channelId and looking up in a map... cache in an array the low numbered + // channels. This value must be of the form 2^x - 1. + private static final int CHANNEL_CACHE_SIZE = 0xff; + private static final int REUSABLE_BYTE_BUFFER_CAPACITY = 65 * 1024; + private final Port _port; + + private AMQShortString _contextKey; + + private String _clientVersion = null; + + private VirtualHost _virtualHost; + + private final Map _channelMap = new HashMap(); + + private final AMQChannel[] _cachedChannels = new AMQChannel[CHANNEL_CACHE_SIZE + 1]; + + /** + * The channels that the latest call to {@link #received(ByteBuffer)} applied to. + * Used so we know which channels we need to call {@link AMQChannel#receivedComplete()} + * on after handling the frames. + * + * Thread-safety: guarded by {@link #_receivedLock}. + */ + private final Set _channelsForCurrentMessage = new HashSet(); + + private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); + + private final AMQStateManager _stateManager; + + private AMQCodecFactory _codecFactory; + + private SaslServer _saslServer; + + private Object _lastReceived; + + private Object _lastSent; + + private volatile boolean _closed; + + // maximum number of channels this session should have + private long _maxNoOfChannels; + + /* AMQP Version for this session */ + private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion(); + private MethodRegistry _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); + private FieldTable _clientProperties; + private final List _taskList = new CopyOnWriteArrayList(); + + private Map _closingChannelsList = new ConcurrentHashMap(); + private ProtocolOutputConverter _protocolOutputConverter; + private Subject _authorizedSubject; + private MethodDispatcher _dispatcher; + + private final long _connectionID; + private Object _reference = new Object(); + + private AMQPConnectionActor _actor; + private LogSubject _logSubject; + + private long _lastIoTime; + + private long _writtenBytes; + private long _readBytes; + + + private long _maxFrameSize; + private final AtomicBoolean _closing = new AtomicBoolean(false); + private long _createTime = System.currentTimeMillis(); + + private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; + + private NetworkConnection _network; + private Sender _sender; + + private volatile boolean _deferFlush; + private long _lastReceivedTime; + private boolean _blocking; + + private final Lock _receivedLock; + private AtomicLong _lastWriteTime = new AtomicLong(System.currentTimeMillis()); + private final Broker _broker; + private final Transport _transport; + + private volatile boolean _closeWhenNoRoute; + private volatile boolean _stopped; + + public AMQProtocolEngine(Broker broker, + NetworkConnection network, + final long connectionId, + Port port, + Transport transport) + { + _broker = broker; + _port = port; + _transport = transport; + _maxNoOfChannels = (Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT); + _receivedLock = new ReentrantLock(); + _stateManager = new AMQStateManager(broker, this); + _codecFactory = new AMQCodecFactory(true, this); + + setNetworkConnection(network); + _connectionID = connectionId; + + _actor = new AMQPConnectionActor(this, _broker.getRootMessageLogger()); + + _logSubject = new ConnectionLogSubject(this); + + _actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false)); + + _closeWhenNoRoute = (Boolean)_broker.getAttribute(Broker.CONNECTION_CLOSE_WHEN_NO_ROUTE); + + initialiseStatistics(); + + } + + public void setNetworkConnection(NetworkConnection network) + { + setNetworkConnection(network, network.getSender()); + } + + public void setNetworkConnection(NetworkConnection network, Sender sender) + { + _network = network; + _sender = sender; + } + + public long getSessionID() + { + return _connectionID; + } + + public LogActor getLogActor() + { + return _actor; + } + + public void setMaxFrameSize(long frameMax) + { + _maxFrameSize = frameMax; + } + + public long getMaxFrameSize() + { + return _maxFrameSize; + } + + public boolean isClosing() + { + return _closing.get(); + } + + public synchronized void flushBatched() + { + _sender.flush(); + } + + + public ClientDeliveryMethod createDeliveryMethod(int channelId) + { + return new WriteDeliverMethod(channelId); + } + + public void received(final ByteBuffer msg) + { + final long arrivalTime = System.currentTimeMillis(); + _lastReceivedTime = arrivalTime; + _lastIoTime = arrivalTime; + + _receivedLock.lock(); + try + { + final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); + final int len = dataBlocks.size(); + for (int i = 0; i < len; i++) + { + AMQDataBlock dataBlock = dataBlocks.get(i); + try + { + dataBlockReceived(dataBlock); + } + catch(AMQConnectionException e) + { + if(_logger.isDebugEnabled()) + { + _logger.debug("Caught AMQConnectionException but will simply stop processing data blocks - the connection should already be closed.", e); + } + break; + } + catch (Exception e) + { + _logger.error("Unexpected exception when processing datablock", e); + closeProtocolSession(); + break; + } + } + receivedComplete(); + } + catch (Exception e) + { + _logger.error("Unexpected exception when processing datablocks", e); + closeProtocolSession(); + } + finally + { + _receivedLock.unlock(); + } + } + + private void receivedComplete() throws AMQException + { + Exception exception = null; + for (AMQChannel channel : _channelsForCurrentMessage) + { + try + { + channel.receivedComplete(); + } + catch(Exception exceptionForThisChannel) + { + if(exception == null) + { + exception = exceptionForThisChannel; + } + _logger.error("Error informing channel that receiving is complete. Channel: " + channel, exceptionForThisChannel); + } + } + + _channelsForCurrentMessage.clear(); + + if(exception != null) + { + throw new AMQException( + AMQConstant.INTERNAL_ERROR, + "Error informing channel that receiving is complete: " + exception.getMessage(), + exception); + } + } + + /** + * Process the data block. + * If the message is for a channel it is added to {@link #_channelsForCurrentMessage}. + * + * @throws an AMQConnectionException if unable to process the data block. In this case, + * the connection is already closed by the time the exception is thrown. If any other + * type of exception is thrown, the connection is not already closed. + */ + private void dataBlockReceived(AMQDataBlock message) throws Exception + { + _lastReceived = message; + if (message instanceof ProtocolInitiation) + { + protocolInitiationReceived((ProtocolInitiation) message); + + } + else if (message instanceof AMQFrame) + { + AMQFrame frame = (AMQFrame) message; + frameReceived(frame); + + } + else + { + throw new AMQException("Unknown message type: " + message.getClass().getName() + ": " + message); + } + } + + /** + * Handle the supplied frame. + * Adds this frame's channel to {@link #_channelsForCurrentMessage}. + * + * @throws an AMQConnectionException if unable to process the data block. In this case, + * the connection is already closed by the time the exception is thrown. If any other + * type of exception is thrown, the connection is not already closed. + */ + private void frameReceived(AMQFrame frame) throws AMQException + { + int channelId = frame.getChannel(); + AMQChannel amqChannel = _channelMap.get(channelId); + if(amqChannel != null) + { + // The _receivedLock is already aquired in the caller + // It is safe to add channel + _channelsForCurrentMessage.add(amqChannel); + } + else + { + // Not an error. The frame is probably a channel Open for this channel id, which + // does not require asynchronous work therefore its absence from + // _channelsForCurrentMessage is ok. + } + + AMQBody body = frame.getBodyFrame(); + + //Look up the Channel's Actor and set that as the current actor + // If that is not available then we can use the ConnectionActor + // that is associated with this AMQMPSession. + LogActor channelActor = null; + if (amqChannel != null) + { + channelActor = amqChannel.getLogActor(); + } + CurrentActor.set(channelActor == null ? _actor : channelActor); + + try + { + long startTime = 0; + String frameToString = null; + if (_logger.isDebugEnabled()) + { + startTime = System.currentTimeMillis(); + frameToString = frame.toString(); + _logger.debug("RECV: " + frame); + } + + // Check that this channel is not closing + if (channelAwaitingClosure(channelId)) + { + if ((frame.getBodyFrame() instanceof ChannelCloseOkBody)) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Channel[" + channelId + "] awaiting closure - processing close-ok"); + } + } + else + { + // The channel has been told to close, we don't process any more frames until + // it's closed. + return; + } + } + + try + { + body.handle(channelId, this); + } + catch(AMQConnectionException e) + { + _logger.info(e.getMessage() + " whilst processing frame: " + body); + closeConnection(channelId, e); + throw e; + } + catch (AMQException e) + { + closeChannel(channelId, e.getErrorCode() == null ? AMQConstant.INTERNAL_ERROR : e.getErrorCode(), e.getMessage()); + throw e; + } + catch (TransportException e) + { + closeChannel(channelId, AMQConstant.CHANNEL_ERROR, e.getMessage()); + throw e; + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Frame handled in " + (System.currentTimeMillis() - startTime) + " ms. Frame: " + frameToString); + } + } + finally + { + CurrentActor.remove(); + } + } + + private synchronized void protocolInitiationReceived(ProtocolInitiation pi) + { + // this ensures the codec never checks for a PI message again + (_codecFactory.getDecoder()).setExpectProtocolInitiation(false); + try + { + // Log incomming protocol negotiation request + _actor.message(ConnectionMessages.OPEN(null, pi.getProtocolMajor() + "-" + pi.getProtocolMinor(), null, false, true, false)); + + ProtocolVersion pv = pi.checkVersion(); // Fails if not correct + + // This sets the protocol version (and hence framing classes) for this session. + setProtocolVersion(pv); + + String mechanisms = _broker.getSubjectCreator(getLocalAddress()).getMechanisms(); + + String locales = "en_US"; + + + FieldTable serverProperties = FieldTableFactory.newFieldTable(); + + serverProperties.setString(ServerPropertyNames.PRODUCT, + QpidProperties.getProductName()); + serverProperties.setString(ServerPropertyNames.VERSION, + QpidProperties.getReleaseVersion()); + serverProperties.setString(ServerPropertyNames.QPID_BUILD, + QpidProperties.getBuildVersion()); + serverProperties.setString(ServerPropertyNames.QPID_INSTANCE_NAME, + _broker.getName()); + serverProperties.setString(ConnectionStartProperties.QPID_CLOSE_WHEN_NO_ROUTE, + String.valueOf(_closeWhenNoRoute)); + + AMQMethodBody responseBody = getMethodRegistry().createConnectionStartBody((short) getProtocolMajorVersion(), + (short) pv.getActualMinorVersion(), + serverProperties, + mechanisms.getBytes(), + locales.getBytes()); + _sender.send(asByteBuffer(responseBody.generateFrame(0))); + _sender.flush(); + + } + catch (AMQException e) + { + _logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion()); + + _sender.send(asByteBuffer(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()))); + _sender.flush(); + } + } + + + private final byte[] _reusableBytes = new byte[REUSABLE_BYTE_BUFFER_CAPACITY]; + private final ByteBuffer _reusableByteBuffer = ByteBuffer.wrap(_reusableBytes); + private final BytesDataOutput _reusableDataOutput = new BytesDataOutput(_reusableBytes); + + private ByteBuffer asByteBuffer(AMQDataBlock block) + { + final int size = (int) block.getSize(); + + final byte[] data; + + + if(size > REUSABLE_BYTE_BUFFER_CAPACITY) + { + data= new byte[size]; + } + else + { + + data = _reusableBytes; + } + _reusableDataOutput.setBuffer(data); + + try + { + block.writePayload(_reusableDataOutput); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + + final ByteBuffer buf; + + if(size <= REUSABLE_BYTE_BUFFER_CAPACITY) + { + buf = _reusableByteBuffer; + buf.position(0); + } + else + { + buf = ByteBuffer.wrap(data); + } + buf.limit(_reusableDataOutput.length()); + + return buf; + } + + public void methodFrameReceived(int channelId, AMQMethodBody methodBody) + { + final AMQMethodEvent evt = new AMQMethodEvent(channelId, methodBody); + + try + { + try + { + boolean wasAnyoneInterested = _stateManager.methodReceived(evt); + + if (!_frameListeners.isEmpty()) + { + for (AMQMethodListener listener : _frameListeners) + { + wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested; + } + } + + if (!wasAnyoneInterested) + { + throw new AMQNoMethodHandlerException(evt); + } + } + catch (AMQChannelException e) + { + if (getChannel(channelId) != null) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Closing channel due to: " + e.getMessage()); + } + + writeFrame(e.getCloseFrame(channelId)); + closeChannel(channelId, e.getErrorCode() == null ? AMQConstant.INTERNAL_ERROR : e.getErrorCode(), e.getMessage()); + } + else + { + if (_logger.isDebugEnabled()) + { + _logger.debug("ChannelException occured on non-existent channel:" + e.getMessage()); + } + + if (_logger.isInfoEnabled()) + { + _logger.info("Closing connection due to: " + e.getMessage()); + } + + AMQConnectionException ce = + evt.getMethod().getConnectionException(AMQConstant.CHANNEL_ERROR, + AMQConstant.CHANNEL_ERROR.getName().toString()); + + _logger.info(e.getMessage() + " whilst processing:" + methodBody); + closeConnection(channelId, ce); + } + } + catch (AMQConnectionException e) + { + _logger.info(e.getMessage() + " whilst processing:" + methodBody); + closeConnection(channelId, e); + } + catch (AMQSecurityException e) + { + AMQConnectionException ce = evt.getMethod().getConnectionException(AMQConstant.ACCESS_REFUSED, e.getMessage()); + _logger.info(e.getMessage() + " whilst processing:" + methodBody); + closeConnection(channelId, ce); + } + } + catch (Exception e) + { + for (AMQMethodListener listener : _frameListeners) + { + listener.error(e); + } + + _logger.error("Unexpected exception while processing frame. Closing connection.", e); + + closeProtocolSession(); + } + } + + public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException + { + + AMQChannel channel = getAndAssertChannel(channelId); + + channel.publishContentHeader(body); + + } + + public void contentBodyReceived(int channelId, ContentBody body) throws AMQException + { + AMQChannel channel = getAndAssertChannel(channelId); + + channel.publishContentBody(body); + } + + public void heartbeatBodyReceived(int channelId, HeartbeatBody body) + { + // NO - OP + } + + /** + * Convenience method that writes a frame to the protocol session. Equivalent to calling + * getProtocolSession().write(). + * + * @param frame the frame to write + */ + public synchronized void writeFrame(AMQDataBlock frame) + { + + final ByteBuffer buf = asByteBuffer(frame); + _writtenBytes += buf.remaining(); + + if(_logger.isDebugEnabled()) + { + _logger.debug("SEND: " + frame); + } + + _sender.send(buf); + final long time = System.currentTimeMillis(); + _lastIoTime = time; + _lastWriteTime.set(time); + + if(!_deferFlush) + { + _sender.flush(); + } + } + + public AMQShortString getContextKey() + { + return _contextKey; + } + + public void setContextKey(AMQShortString contextKey) + { + _contextKey = contextKey; + } + + public List getChannels() + { + synchronized (_channelMap) + { + return new ArrayList(_channelMap.values()); + } + } + + public AMQChannel getAndAssertChannel(int channelId) throws AMQException + { + AMQChannel channel = getChannel(channelId); + if (channel == null) + { + throw new AMQException(AMQConstant.NOT_FOUND, "Channel not found with id:" + channelId); + } + + return channel; + } + + public AMQChannel getChannel(int channelId) + { + final AMQChannel channel = + ((channelId & CHANNEL_CACHE_SIZE) == channelId) ? _cachedChannels[channelId] : _channelMap.get(channelId); + if ((channel == null) || channel.isClosing()) + { + return null; + } + else + { + return channel; + } + } + + public boolean channelAwaitingClosure(int channelId) + { + return !_closingChannelsList.isEmpty() && _closingChannelsList.containsKey(channelId); + } + + public void addChannel(AMQChannel channel) throws AMQException + { + if (_closed) + { + throw new AMQException("Session is closed"); + } + + final int channelId = channel.getChannelId(); + + if (_closingChannelsList.containsKey(channelId)) + { + throw new AMQException("Session is marked awaiting channel close"); + } + + if (_channelMap.size() == _maxNoOfChannels) + { + String errorMessage = + toString() + ": maximum number of channels has been reached (" + _maxNoOfChannels + + "); can't create channel"; + _logger.error(errorMessage); + throw new AMQException(AMQConstant.NOT_ALLOWED, errorMessage); + } + else + { + synchronized (_channelMap) + { + _channelMap.put(channel.getChannelId(), channel); + + if(_blocking) + { + channel.block(); + } + } + } + + if (((channelId & CHANNEL_CACHE_SIZE) == channelId)) + { + _cachedChannels[channelId] = channel; + } + } + + public Long getMaximumNumberOfChannels() + { + return _maxNoOfChannels; + } + + public void setMaximumNumberOfChannels(Long value) + { + _maxNoOfChannels = value; + } + + public void commitTransactions(AMQChannel channel) throws AMQException + { + if ((channel != null) && channel.isTransactional()) + { + channel.commit(); + } + } + + public void rollbackTransactions(AMQChannel channel) throws AMQException + { + if ((channel != null) && channel.isTransactional()) + { + channel.rollback(); + } + } + + /** + * Close a specific channel. This will remove any resources used by the channel, including:

  • any queue + * subscriptions (this may in turn remove queues if they are auto delete
+ * + * @param channelId id of the channel to close + * + * @throws AMQException if an error occurs closing the channel + * @throws IllegalArgumentException if the channel id is not valid + */ + @Override + public void closeChannel(int channelId) throws AMQException + { + closeChannel(channelId, null, null); + } + + public void closeChannel(int channelId, AMQConstant cause, String message) throws AMQException + { + final AMQChannel channel = getChannel(channelId); + if (channel == null) + { + throw new IllegalArgumentException("Unknown channel id"); + } + else + { + try + { + channel.close(cause, message); + markChannelAwaitingCloseOk(channelId); + } + finally + { + removeChannel(channelId); + } + } + } + + public void closeChannelOk(int channelId) + { + // todo QPID-847 - This is called from two lcoations ChannelCloseHandler and ChannelCloseOkHandler. + // When it is the CC_OK_Handler then it makes sence to remove the channel else we will leak memory. + // We do it from the Close Handler as we are sending the OK back to the client. + // While this is AMQP spec compliant. The Java client in the event of an IllegalArgumentException + // will send a close-ok.. Where we should call removeChannel. + // However, due to the poor exception handling on the client. The client-user will be notified of the + // InvalidArgument and if they then decide to close the session/connection then the there will be time + // for that to occur i.e. a new close method be sent before the exeption handling can mark the session closed. + + _closingChannelsList.remove(channelId); + } + + private void markChannelAwaitingCloseOk(int channelId) + { + _closingChannelsList.put(channelId, System.currentTimeMillis()); + } + + /** + * In our current implementation this is used by the clustering code. + * + * @param channelId The channel to remove + */ + public void removeChannel(int channelId) + { + synchronized (_channelMap) + { + _channelMap.remove(channelId); + + if ((channelId & CHANNEL_CACHE_SIZE) == channelId) + { + _cachedChannels[channelId] = null; + } + } + } + + /** + * Initialise heartbeats on the session. + * + * @param delay delay in seconds (not ms) + */ + public void initHeartbeats(int delay) + { + if (delay > 0) + { + _network.setMaxWriteIdle(delay); + _network.setMaxReadIdle(BrokerProperties.HEARTBEAT_TIMEOUT_FACTOR * delay); + } + else + { + _network.setMaxWriteIdle(0); + _network.setMaxReadIdle(0); + } + } + + /** + * Closes all channels that were opened by this protocol session. This frees up all resources used by the channel. + * + * @throws AMQException if an error occurs while closing any channel + */ + private void closeAllChannels() throws AMQException + { + for (AMQChannel channel : getChannels()) + { + channel.close(); + } + synchronized (_channelMap) + { + _channelMap.clear(); + } + for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++) + { + _cachedChannels[i] = null; + } + } + + /** This must be called when the session is _closed in order to free up any resources managed by the session. */ + @Override + public void closeSession() throws AMQException + { + if(_closing.compareAndSet(false,true)) + { + // force sync of outstanding async work + _receivedLock.lock(); + try + { + receivedComplete(); + } + finally + { + _receivedLock.unlock(); + } + + // REMOVE THIS SHOULD NOT BE HERE. + if (CurrentActor.get() == null) + { + CurrentActor.set(_actor); + } + if (!_closed) + { + if (_virtualHost != null) + { + _virtualHost.getConnectionRegistry().deregisterConnection(this); + } + + closeAllChannels(); + + for (Task task : _taskList) + { + task.doTask(this); + } + + synchronized(this) + { + _closed = true; + notifyAll(); + } + CurrentActor.get().message(_logSubject, ConnectionMessages.CLOSE()); + } + } + else + { + synchronized(this) + { + while(!_closed) + { + try + { + wait(1000); + } + catch (InterruptedException e) + { + + } + } + } + } + } + + private void closeConnection(int channelId, AMQConnectionException e) throws AMQException + { + try + { + if (_logger.isInfoEnabled()) + { + _logger.info("Closing connection due to: " + e); + } + + markChannelAwaitingCloseOk(channelId); + closeSession(); + } + finally + { + try + { + _stateManager.changeState(AMQState.CONNECTION_CLOSING); + writeFrame(e.getCloseFrame(channelId)); + } + finally + { + closeProtocolSession(); + } + } + + + } + + @Override + public void closeProtocolSession() + { + _network.close(); + + try + { + _stateManager.changeState(AMQState.CONNECTION_CLOSED); + } + catch (AMQException e) + { + _logger.info(e.getMessage()); + } + catch (TransportException e) + { + _logger.info(e.getMessage()); + } + } + + public String toString() + { + return getRemoteAddress() + "(" + (getAuthorizedPrincipal() == null ? "?" : getAuthorizedPrincipal().getName() + ")"); + } + + public String dump() + { + return this + " last_sent=" + _lastSent + " last_received=" + _lastReceived; + } + + /** @return an object that can be used to identity */ + public Object getKey() + { + return getRemoteAddress(); + } + + /** + * Get the fully qualified domain name of the local address to which this session is bound. Since some servers may + * be bound to multiple addresses this could vary depending on the acceptor this session was created from. + * + * @return a String FQDN + */ + public String getLocalFQDN() + { + SocketAddress address = _network.getLocalAddress(); + if (address instanceof InetSocketAddress) + { + return ((InetSocketAddress) address).getHostName(); + } + else + { + throw new IllegalArgumentException("Unsupported socket address class: " + address); + } + } + + public SaslServer getSaslServer() + { + return _saslServer; + } + + public void setSaslServer(SaslServer saslServer) + { + _saslServer = saslServer; + } + + public void setClientProperties(FieldTable clientProperties) + { + _clientProperties = clientProperties; + if (_clientProperties != null) + { + String closeWhenNoRoute = _clientProperties.getString(ConnectionStartProperties.QPID_CLOSE_WHEN_NO_ROUTE); + if (closeWhenNoRoute != null) + { + _closeWhenNoRoute = Boolean.parseBoolean(closeWhenNoRoute); + if(_logger.isDebugEnabled()) + { + _logger.debug("Client set closeWhenNoRoute=" + _closeWhenNoRoute + " for protocol engine " + this); + } + } + + _clientVersion = _clientProperties.getString(ConnectionStartProperties.VERSION_0_8); + + if (_clientProperties.getString(ConnectionStartProperties.CLIENT_ID_0_8) != null) + { + String clientID = _clientProperties.getString(ConnectionStartProperties.CLIENT_ID_0_8); + setContextKey(new AMQShortString(clientID)); + + // Log the Opening of the connection for this client + _actor.message(ConnectionMessages.OPEN(clientID, _protocolVersion.toString(), _clientVersion, true, true, true)); + } + } + } + + private void setProtocolVersion(ProtocolVersion pv) + { + _protocolVersion = pv; + _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); + _protocolOutputConverter = ProtocolOutputConverterRegistry.getConverter(this); + _dispatcher = ServerMethodDispatcherImpl.createMethodDispatcher(_stateManager, _protocolVersion); + } + + public byte getProtocolMajorVersion() + { + return _protocolVersion.getMajorVersion(); + } + + public ProtocolVersion getProtocolVersion() + { + return _protocolVersion; + } + + public byte getProtocolMinorVersion() + { + return _protocolVersion.getMinorVersion(); + } + + public boolean isProtocolVersion(byte major, byte minor) + { + return (getProtocolMajorVersion() == major) && (getProtocolMinorVersion() == minor); + } + + public MethodRegistry getRegistry() + { + return getMethodRegistry(); + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public void setVirtualHost(VirtualHost virtualHost) throws AMQException + { + _virtualHost = virtualHost; + + _virtualHost.getConnectionRegistry().registerConnection(this); + + } + + public void addSessionCloseTask(Task task) + { + _taskList.add(task); + } + + public void removeSessionCloseTask(Task task) + { + _taskList.remove(task); + } + + public ProtocolOutputConverter getProtocolOutputConverter() + { + return _protocolOutputConverter; + } + + public void setAuthorizedSubject(final Subject authorizedSubject) + { + if (authorizedSubject == null) + { + throw new IllegalArgumentException("authorizedSubject cannot be null"); + } + _authorizedSubject = authorizedSubject; + } + + public Subject getAuthorizedSubject() + { + return _authorizedSubject; + } + + public Principal getAuthorizedPrincipal() + { + return _authorizedSubject == null ? null : AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(_authorizedSubject); + } + + public SocketAddress getRemoteAddress() + { + return _network.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _network.getLocalAddress(); + } + + public Principal getPeerPrincipal() + { + return _network.getPeerPrincipal(); + } + + public MethodRegistry getMethodRegistry() + { + return _methodRegistry; + } + + public MethodDispatcher getMethodDispatcher() + { + return _dispatcher; + } + + public void closed() + { + try + { + try + { + closeSession(); + } + finally + { + closeProtocolSession(); + } + } + catch (AMQException e) + { + _logger.error("Could not close protocol engine", e); + } + catch (TransportException e) + { + _logger.error("Could not close protocol engine", e); + } + } + + public void readerIdle() + { + // TODO - enforce disconnect on lack of inbound data + } + + public synchronized void writerIdle() + { + writeFrame(HeartbeatBody.FRAME); + } + + public void exception(Throwable throwable) + { + if (throwable instanceof AMQProtocolHeaderException) + { + writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())); + _sender.close(); + + _logger.error("Error in protocol initiation " + this + ":" + getRemoteAddress() + " :" + throwable.getMessage(), throwable); + } + else if (throwable instanceof IOException) + { + _logger.error("IOException caught in" + this + ", session closed implictly: " + throwable); + } + else + { + _logger.error("Exception caught in" + this + ", closing session explictly: " + throwable, throwable); + + + MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion()); + ConnectionCloseBody closeBody = methodRegistry.createConnectionCloseBody(200,new AMQShortString(throwable.getMessage()),0,0); + + writeFrame(closeBody.generateFrame(0)); + + _sender.close(); + } + } + + public void init() + { + // Do nothing + } + + public void setSender(Sender sender) + { + // Do nothing + } + + public long getReadBytes() + { + return _readBytes; + } + + public long getWrittenBytes() + { + return _writtenBytes; + } + + public long getLastIoTime() + { + return _lastIoTime; + } + + @Override + public Port getPort() + { + return _port; + } + + @Override + public Transport getTransport() + { + return _transport; + } + + @Override + public void stop() + { + _stopped = true; + } + + @Override + public boolean isStopped() + { + return _stopped; + } + + public long getLastReceivedTime() + { + return _lastReceivedTime; + } + + public String getClientVersion() + { + return _clientVersion; + } + + public String getPrincipalAsString() + { + return getAuthId(); + } + + public long getSessionCountLimit() + { + return getMaximumNumberOfChannels(); + } + + public Boolean isIncoming() + { + return true; + } + + public Boolean isSystemConnection() + { + return false; + } + + public Boolean isFederationLink() + { + return false; + } + + public String getAuthId() + { + return getAuthorizedPrincipal().getName(); + } + + public Integer getRemotePID() + { + return null; + } + + public String getRemoteProcessName() + { + return null; + } + + public Integer getRemoteParentPID() + { + return null; + } + + public boolean isDurable() + { + return false; + } + + public long getConnectionId() + { + return getSessionID(); + } + + public String getAddress() + { + return String.valueOf(getRemoteAddress()); + } + + public long getCreateTime() + { + return _createTime; + } + + public Boolean isShadow() + { + return false; + } + + public void mgmtClose() + { + MethodRegistry methodRegistry = getMethodRegistry(); + ConnectionCloseBody responseBody = + methodRegistry.createConnectionCloseBody( + AMQConstant.REPLY_SUCCESS.getCode(), + new AMQShortString("The connection was closed using the broker's management interface."), + 0,0); + + // This seems ugly but because we use closeConnection in both normal + // broker operation and as part of the management interface it cannot + // be avoided. The Current Actor will be null when this method is + // called via the QMF management interface. As such we need to set one. + boolean removeActor = false; + if (CurrentActor.get() == null) + { + removeActor = true; + CurrentActor.set(new ManagementActor(_actor.getRootMessageLogger())); + } + + try + { + writeFrame(responseBody.generateFrame(0)); + + try + { + + closeSession(); + } + catch (AMQException ex) + { + throw new RuntimeException(ex); + } + } + finally + { + if (removeActor) + { + CurrentActor.remove(); + } + } + } + + public void mgmtCloseChannel(int channelId) + { + MethodRegistry methodRegistry = getMethodRegistry(); + ChannelCloseBody responseBody = + methodRegistry.createChannelCloseBody( + AMQConstant.REPLY_SUCCESS.getCode(), + new AMQShortString("The channel was closed using the broker's management interface."), + 0,0); + + // This seems ugly but because we use AMQChannel.close() in both normal + // broker operation and as part of the management interface it cannot + // be avoided. The Current Actor will be null when this method is + // called via the QMF management interface. As such we need to set one. + boolean removeActor = false; + if (CurrentActor.get() == null) + { + removeActor = true; + CurrentActor.set(new ManagementActor(_actor.getRootMessageLogger())); + } + + try + { + writeFrame(responseBody.generateFrame(channelId)); + + try + { + closeChannel(channelId); + } + catch (AMQException ex) + { + throw new RuntimeException(ex); + } + } + finally + { + if (removeActor) + { + CurrentActor.remove(); + } + } + } + + public String getClientID() + { + return getContextKey().toString(); + } + + public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException + { + int channelId = ((AMQChannel)session).getChannelId(); + closeChannel(channelId, cause, message); + + MethodRegistry methodRegistry = getMethodRegistry(); + ChannelCloseBody responseBody = + methodRegistry.createChannelCloseBody( + cause.getCode(), + new AMQShortString(message), + 0,0); + + writeFrame(responseBody.generateFrame(channelId)); + } + + public void close(AMQConstant cause, String message) throws AMQException + { + closeConnection(0, new AMQConnectionException(cause, message, 0, 0, + getProtocolOutputConverter().getProtocolMajorVersion(), + getProtocolOutputConverter().getProtocolMinorVersion(), + (Throwable) null)); + } + + public void block() + { + synchronized (_channelMap) + { + if(!_blocking) + { + _blocking = true; + for(AMQChannel channel : _channelMap.values()) + { + channel.block(); + } + } + } + } + + public void unblock() + { + synchronized (_channelMap) + { + if(_blocking) + { + _blocking = false; + for(AMQChannel channel : _channelMap.values()) + { + channel.unblock(); + } + } + } + } + + public boolean isClosed() + { + return _closed; + } + + public List getSessionModels() + { + return new ArrayList(getChannels()); + } + + public LogSubject getLogSubject() + { + return _logSubject; + } + + public void registerMessageDelivered(long messageSize) + { + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); + _virtualHost.registerMessageDelivered(messageSize); + } + + public void registerMessageReceived(long messageSize, long timestamp) + { + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); + _virtualHost.registerMessageReceived(messageSize, timestamp); + } + + public StatisticsCounter getMessageReceiptStatistics() + { + return _messagesReceived; + } + + public StatisticsCounter getDataReceiptStatistics() + { + return _dataReceived; + } + + public StatisticsCounter getMessageDeliveryStatistics() + { + return _messagesDelivered; + } + + public StatisticsCounter getDataDeliveryStatistics() + { + return _dataDelivered; + } + + public void resetStatistics() + { + _messagesDelivered.reset(); + _dataDelivered.reset(); + _messagesReceived.reset(); + _dataReceived.reset(); + } + + public void initialiseStatistics() + { + _messagesDelivered = new StatisticsCounter("messages-delivered-" + getSessionID()); + _dataDelivered = new StatisticsCounter("data-delivered-" + getSessionID()); + _messagesReceived = new StatisticsCounter("messages-received-" + getSessionID()); + _dataReceived = new StatisticsCounter("data-received-" + getSessionID()); + } + + public boolean isSessionNameUnique(byte[] name) + { + // 0-8/0-9/0-9-1 sessions don't have names + return true; + } + + public String getRemoteAddressString() + { + return String.valueOf(getRemoteAddress()); + } + + public String getClientId() + { + return String.valueOf(getContextKey()); + } + + public void setDeferFlush(boolean deferFlush) + { + _deferFlush = deferFlush; + } + + public String getUserName() + { + return getAuthorizedPrincipal().getName(); + } + + public final class WriteDeliverMethod + implements ClientDeliveryMethod + { + private final int _channelId; + + public WriteDeliverMethod(int channelId) + { + _channelId = channelId; + } + + public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) + throws AMQException + { + registerMessageDelivered(entry.getMessage().getSize()); + _protocolOutputConverter.writeDeliver(entry, _channelId, deliveryTag, ((SubscriptionImpl)sub).getConsumerTag()); + entry.incrementDeliveryCount(); + } + + } + + public Object getReference() + { + return _reference; + } + + public Lock getReceivedLock() + { + return _receivedLock; + } + + @Override + public long getLastReadTime() + { + return _lastReceivedTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime.get(); + } + + @Override + public boolean isCloseWhenNoRoute() + { + return _closeWhenNoRoute; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.java new file mode 100644 index 0000000000..f5c43003a4 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.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.server.protocol.v0_8; + +import java.util.Collection; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; + +import java.util.Set; +import org.apache.qpid.server.message.AMQMessageHeader; + +public class ContentHeaderBodyAdapter implements AMQMessageHeader +{ + private final ContentHeaderBody _contentHeaderBody; + + public ContentHeaderBodyAdapter(ContentHeaderBody contentHeaderBody) + { + _contentHeaderBody = contentHeaderBody; + } + + private BasicContentHeaderProperties getProperties() + { + return (BasicContentHeaderProperties) _contentHeaderBody.getProperties(); + } + + public String getCorrelationId() + { + return getProperties().getCorrelationIdAsString(); + } + + public long getExpiration() + { + return getProperties().getExpiration(); + } + + public String getUserId() + { + return getProperties().getUserIdAsString(); + } + + public String getAppId() + { + return getProperties().getAppIdAsString(); + } + + public String getMessageId() + { + return getProperties().getMessageIdAsString(); + } + + public String getMimeType() + { + return getProperties().getContentTypeAsString(); + } + + public String getEncoding() + { + return getProperties().getEncodingAsString(); + } + + public byte getPriority() + { + return getProperties().getPriority(); + } + + public long getTimestamp() + { + return getProperties().getTimestamp(); + } + + public String getType() + { + return getProperties().getTypeAsString(); + } + + public String getReplyTo() + { + return getProperties().getReplyToAsString(); + } + + public String getReplyToExchange() + { + // TODO + return getReplyTo(); + } + + public String getReplyToRoutingKey() + { + // TODO + return getReplyTo(); + + } + + public Object getHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.get(name); + } + + public boolean containsHeaders(Set names) + { + FieldTable ft = getProperties().getHeaders(); + for(String name : names) + { + if(!ft.containsKey(name)) + { + return false; + } + } + return true; + } + + @Override + public Collection getHeaderNames() + { + FieldTable ft = getProperties().getHeaders(); + return ft.keys(); + } + + public boolean containsHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.containsKey(name); + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java new file mode 100644 index 0000000000..5e416b52ca --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java @@ -0,0 +1,133 @@ +/* + * + * 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.v0_8; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.ServerTransaction; + +import java.util.Map; + +public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor +{ + private static final Logger _log = Logger.getLogger(ExtractResendAndRequeue.class); + + private final Map _msgToRequeue; + private final Map _msgToResend; + private final boolean _requeueIfUnabletoResend; + private final UnacknowledgedMessageMap _unacknowledgedMessageMap; + private final MessageStore _transactionLog; + + public ExtractResendAndRequeue(UnacknowledgedMessageMap unacknowledgedMessageMap, + Map msgToRequeue, + Map msgToResend, + boolean requeueIfUnabletoResend, + MessageStore txnLog) + { + _unacknowledgedMessageMap = unacknowledgedMessageMap; + _msgToRequeue = msgToRequeue; + _msgToResend = msgToResend; + _requeueIfUnabletoResend = requeueIfUnabletoResend; + _transactionLog = txnLog; + } + + public boolean callback(final long deliveryTag, QueueEntry message) throws AMQException + { + + message.setRedelivered(); + final Subscription subscription = message.getDeliveredSubscription(); + if (subscription != null) + { + // Consumer exists + if (!subscription.isClosed()) + { + _msgToResend.put(deliveryTag, message); + } + else // consumer has gone + { + _msgToRequeue.put(deliveryTag, message); + } + } + else + { + // Message has no consumer tag, so was "delivered" to a GET + // or consumer no longer registered + // cannot resend, so re-queue. + if (!message.isQueueDeleted()) + { + if (_requeueIfUnabletoResend) + { + _msgToRequeue.put(deliveryTag, message); + } + else + { + + dequeueEntry(message); + _log.info("No DeadLetter Queue and requeue not requested so dropping message:" + message); + } + } + else + { + dequeueEntry(message); + _log.warn("Message.queue is null and no DeadLetter Queue so dropping message:" + message); + } + } + + // false means continue processing + return false; + } + + + private void dequeueEntry(final QueueEntry node) + { + ServerTransaction txn = new AutoCommitTransaction(_transactionLog); + dequeueEntry(node, txn); + } + + private void dequeueEntry(final QueueEntry node, ServerTransaction txn) + { + txn.dequeue(node.getQueue(), node.getMessage(), + new ServerTransaction.Action() + { + + public void postCommit() + { + node.discard(); + } + + public void onRollback() + { + + } + }); + } + + public void visitComplete() + { + _unacknowledgedMessageMap.clear(); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java new file mode 100644 index 0000000000..c539f793fe --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.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.server.protocol.v0_8; + +import java.util.Collection; +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.EncodingUtils; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.util.ByteBufferOutputStream; +import org.apache.qpid.util.ByteBufferInputStream; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Set; + +/** + * Encapsulates a publish body and a content header. In the context of the message store these are treated as a + * single unit. + */ +public class MessageMetaData implements StorableMessageMetaData +{ + private MessagePublishInfo _messagePublishInfo; + + private ContentHeaderBody _contentHeaderBody; + + private int _contentChunkCount; + + private long _arrivalTime; + private static final byte MANDATORY_FLAG = 1; + private static final byte IMMEDIATE_FLAG = 2; + public static final MessageMetaDataType.Factory FACTORY = new MetaDataFactory(); + + public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount) + { + this(publishBody,contentHeaderBody, contentChunkCount, System.currentTimeMillis()); + } + + public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount, long arrivalTime) + { + _contentHeaderBody = contentHeaderBody; + _messagePublishInfo = publishBody; + _contentChunkCount = contentChunkCount; + _arrivalTime = arrivalTime; + } + + public int getContentChunkCount() + { + return _contentChunkCount; + } + + public void setContentChunkCount(int contentChunkCount) + { + _contentChunkCount = contentChunkCount; + } + + public ContentHeaderBody getContentHeaderBody() + { + return _contentHeaderBody; + } + + public void setContentHeaderBody(ContentHeaderBody contentHeaderBody) + { + _contentHeaderBody = contentHeaderBody; + } + + public MessagePublishInfo getMessagePublishInfo() + { + return _messagePublishInfo; + } + + public void setMessagePublishInfo(MessagePublishInfo messagePublishInfo) + { + _messagePublishInfo = messagePublishInfo; + } + + public long getArrivalTime() + { + return _arrivalTime; + } + + public void setArrivalTime(long arrivalTime) + { + _arrivalTime = arrivalTime; + } + + public MessageMetaDataType getType() + { + return MessageMetaDataType.META_DATA_0_8; + } + + public int getStorableSize() + { + int size = _contentHeaderBody.getSize(); + size += 4; + size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getExchange()); + size += EncodingUtils.encodedShortStringLength(_messagePublishInfo.getRoutingKey()); + size += 1; // flags for immediate/mandatory + size += EncodingUtils.encodedLongLength(); + + return size; + } + + + public int writeToBuffer(int offset, ByteBuffer dest) + { + int oldPosition = dest.position(); + try + { + + DataOutputStream dataOutputStream = new DataOutputStream(new ByteBufferOutputStream(dest)); + EncodingUtils.writeInteger(dataOutputStream, _contentHeaderBody.getSize()); + _contentHeaderBody.writePayload(dataOutputStream); + EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getExchange()); + EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getRoutingKey()); + byte flags = 0; + if(_messagePublishInfo.isMandatory()) + { + flags |= MANDATORY_FLAG; + } + if(_messagePublishInfo.isImmediate()) + { + flags |= IMMEDIATE_FLAG; + } + dest.put(flags); + dest.putLong(_arrivalTime); + + } + catch (IOException e) + { + // This shouldn't happen as we are not actually using anything that can throw an IO Exception + throw new RuntimeException(e); + } + + return dest.position()-oldPosition; + } + + public int getContentSize() + { + return (int) _contentHeaderBody.getBodySize(); + } + + public boolean isPersistent() + { + BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.getProperties()); + return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT; + } + + private static class MetaDataFactory implements MessageMetaDataType.Factory + { + + + public MessageMetaData createMetaData(ByteBuffer buf) + { + try + { + ByteBufferInputStream bbis = new ByteBufferInputStream(buf); + DataInputStream dais = new DataInputStream(bbis); + int size = EncodingUtils.readInteger(dais); + ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(dais, size); + final AMQShortString exchange = EncodingUtils.readAMQShortString(dais); + final AMQShortString routingKey = EncodingUtils.readAMQShortString(dais); + + final byte flags = EncodingUtils.readByte(dais); + long arrivalTime = EncodingUtils.readLong(dais); + + MessagePublishInfo publishBody = + new MessagePublishInfo() + { + + public AMQShortString getExchange() + { + return exchange; + } + + public void setExchange(AMQShortString exchange) + { + } + + public boolean isImmediate() + { + return (flags & IMMEDIATE_FLAG) != 0; + } + + public boolean isMandatory() + { + return (flags & MANDATORY_FLAG) != 0; + } + + public AMQShortString getRoutingKey() + { + return routingKey; + } + }; + return new MessageMetaData(publishBody, chb, 0, arrivalTime); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + + } + }; + + public AMQMessageHeader getMessageHeader() + { + return new MessageHeaderAdapter(); + } + + private final class MessageHeaderAdapter implements AMQMessageHeader + { + private BasicContentHeaderProperties getProperties() + { + return (BasicContentHeaderProperties) getContentHeaderBody().getProperties(); + } + + public String getUserId() + { + return getProperties().getUserIdAsString(); + } + + public String getAppId() + { + return getProperties().getAppIdAsString(); + } + + public String getCorrelationId() + { + return getProperties().getCorrelationIdAsString(); + } + + public long getExpiration() + { + return getProperties().getExpiration(); + } + + public String getMessageId() + { + return getProperties().getMessageIdAsString(); + } + + public String getMimeType() + { + return getProperties().getContentTypeAsString(); + } + + public String getEncoding() + { + return getProperties().getEncodingAsString(); + } + + public byte getPriority() + { + return getProperties().getPriority(); + } + + public long getTimestamp() + { + return getProperties().getTimestamp(); + } + + public String getType() + { + return getProperties().getTypeAsString(); + } + + public String getReplyTo() + { + return getProperties().getReplyToAsString(); + } + + public String getReplyToExchange() + { + // TODO + return getReplyTo(); + } + + public String getReplyToRoutingKey() + { + // TODO + return getReplyTo(); + } + + public Object getHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.get(name); + } + + public boolean containsHeaders(Set names) + { + FieldTable ft = getProperties().getHeaders(); + for(String name : names) + { + if(!ft.containsKey(name)) + { + return false; + } + } + return true; + } + + @Override + public Collection getHeaderNames() + { + return getProperties().getHeaders().keys(); + } + + public boolean containsHeader(String name) + { + FieldTable ft = getProperties().getHeaders(); + return ft.containsKey(name); + } + + + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java new file mode 100644 index 0000000000..c0d55dd438 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java @@ -0,0 +1,88 @@ +/* + * + * 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.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.protocol.v0_10.FlowCreditManager_0_10; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_10.Subscription_0_10; +import org.apache.qpid.server.protocol.v0_10.ServerSession; +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.transport.MessageAcceptMode; +import org.apache.qpid.transport.MessageAcquireMode; +import org.apache.qpid.transport.MessageFlowMode; + +import java.util.Map; + +/** + * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory + * primarily assists testing although in future more sophisticated subscribers may need a different subscription + * implementation. + * + * @see org.apache.qpid.server.queue.AMQQueue + */ +public interface SubscriptionFactory +{ + Subscription createSubscription(int channel, + AMQProtocolSession protocolSession, + AMQShortString consumerTag, + boolean acks, + FieldTable filters, + boolean noLocal, FlowCreditManager creditManager) throws AMQException; + + + Subscription createSubscription(AMQChannel channel, + AMQProtocolSession protocolSession, + AMQShortString consumerTag, + boolean acks, + FieldTable filters, + boolean noLocal, + FlowCreditManager creditManager, + ClientDeliveryMethod clientMethod, + RecordDeliveryMethod recordMethod + ) + throws AMQException; + + + SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel, + AMQProtocolSession session, + AMQShortString consumerTag, + FieldTable filters, + boolean noLocal, + FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod) throws AMQException; + + Subscription_0_10 createSubscription(final ServerSession session, + final String destination, + final MessageAcceptMode acceptMode, + final MessageAcquireMode acquireMode, + final MessageFlowMode flowMode, + final FlowCreditManager_0_10 creditManager, + final FilterManager filterManager, + final Map arguments); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java new file mode 100644 index 0000000000..286e62c18a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.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.server.protocol.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.common.AMQPFilterTypes; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.protocol.v0_10.FlowCreditManager_0_10; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_10.Subscription_0_10; +import org.apache.qpid.server.protocol.v0_10.ServerSession; +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.transport.MessageAcceptMode; +import org.apache.qpid.transport.MessageAcquireMode; +import org.apache.qpid.transport.MessageFlowMode; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +public class SubscriptionFactoryImpl implements SubscriptionFactory +{ + private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0); + + 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, getNextSubscriptionId()); + } + else if(acks) + { + return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); + } + else + { + return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); + } + } + + public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel, + final AMQProtocolSession session, + final AMQShortString consumerTag, + final FieldTable filters, + final boolean noLocal, + final FlowCreditManager creditManager, + final ClientDeliveryMethod deliveryMethod, + final RecordDeliveryMethod recordMethod) throws AMQException + { + return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId()); + } + + public Subscription_0_10 createSubscription(final ServerSession session, + final String destination, + final MessageAcceptMode acceptMode, + final MessageAcquireMode acquireMode, + final MessageFlowMode flowMode, + final FlowCreditManager_0_10 creditManager, + final FilterManager filterManager, + final Map arguments) + { + return new Subscription_0_10(session, destination, acceptMode, acquireMode, + flowMode, creditManager, filterManager, arguments, getNextSubscriptionId()); + } + + public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl(); + + private static long getNextSubscriptionId() + { + return SUB_ID_GENERATOR.getAndIncrement(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java new file mode 100644 index 0000000000..67e7452b15 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java @@ -0,0 +1,849 @@ +/* + * + * 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.v0_8; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.common.AMQPFilterTypes; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.filter.FilterManagerFactory; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.SubscriptionActor; +import org.apache.qpid.server.logging.messages.SubscriptionMessages; +import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +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.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.ServerTransaction; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Encapsulation of a supscription to a queue.

Ties together the protocol session of a subscriber, the consumer tag + * that was given out by the broker and the channel id.

+ */ +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 = new AtomicReference(State.ACTIVE); + private volatile AMQQueue.Context _queueContext; + + private final ClientDeliveryMethod _deliveryMethod; + private final RecordDeliveryMethod _recordMethod; + + private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); + + private final Map _properties = new ConcurrentHashMap(); + + private final Lock _stateChangeLock; + + private final long _subscriptionID; + private LogSubject _logSubject; + private LogActor _logActor; + private final AtomicLong _deliveredCount = new AtomicLong(0); + private final AtomicLong _deliveredBytes = new AtomicLong(0); + + private final AtomicLong _unacknowledgedCount = new AtomicLong(0); + private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); + + private long _createTime = System.currentTimeMillis(); + + + static final class BrowserSubscription extends SubscriptionImpl + { + public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession, + AMQShortString consumerTag, FieldTable filters, + boolean noLocal, FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod, + long subscriptionID) + throws AMQException + { + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + } + + + 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 entry + * @param batch + * @throws AMQException + */ + @Override + public void send(QueueEntry entry, boolean batch) 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(entry, deliveryTag); + } + + } + + @Override + public boolean wouldSuspend(QueueEntry msg) + { + return false; + } + + } + + public static class NoAckSubscription extends SubscriptionImpl + { + private volatile AutoCommitTransaction _txn; + + public NoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, + AMQShortString consumerTag, FieldTable filters, + boolean noLocal, FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod, + long subscriptionID) + throws AMQException + { + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + } + + + public boolean isBrowser() + { + return false; + } + + @Override + public boolean isExplicitAcknowledge() + { + 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 + * @param batch + * @throws AMQException + */ + @Override + public void send(QueueEntry entry, boolean batch) throws AMQException + { + // 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(_txn == null) + { + _txn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); + } + _txn.dequeue(getQueue(), entry.getMessage(), NOOP); + + entry.dequeue(); + + synchronized (getChannel()) + { + getChannel().getProtocolSession().setDeferFlush(batch); + long deliveryTag = getChannel().getNextDeliveryTag(); + + sendToClient(entry, deliveryTag); + + } + entry.dispose(); + + + } + + @Override + public boolean wouldSuspend(QueueEntry msg) + { + return false; + } + + private static final ServerTransaction.Action NOOP = + new ServerTransaction.Action() + { + @Override + public void postCommit() + { + } + + @Override + public void onRollback() + { + } + }; + } + + /** + * NoAck Subscription for use with BasicGet method. + */ + 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, + long subscriptionID) + throws AMQException + { + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + } + + public boolean isTransient() + { + return true; + } + + public boolean wouldSuspend(QueueEntry msg) + { + return !getCreditManager().useCreditForMessage(msg.getMessage().getSize()); + } + + } + + static final class AckSubscription extends SubscriptionImpl + { + public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, + AMQShortString consumerTag, FieldTable filters, + boolean noLocal, FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod, + long subscriptionID) + throws AMQException + { + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + } + + + 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 + * @param batch + * @throws AMQException + */ + @Override + public void send(QueueEntry entry, boolean batch) throws AMQException + { + + + synchronized (getChannel()) + { + getChannel().getProtocolSession().setDeferFlush(batch); + long deliveryTag = getChannel().getNextDeliveryTag(); + + addUnacknowledgedMessage(entry); + recordMessageDelivery(entry, deliveryTag); + sendToClient(entry, deliveryTag); + + + } + } + + + + } + + + private static final Logger _logger = Logger.getLogger(SubscriptionImpl.class); + + private final AMQChannel _channel; + + private final AMQShortString _consumerTag; + + + private boolean _noLocal; + + private final FlowCreditManager _creditManager; + + private FilterManager _filters; + + private final Boolean _autoClose; + + 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, + long subscriptionID) + throws AMQException + { + _subscriptionID = subscriptionID; + _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 AMQSessionModel getSessionModel() + { + return _channel; + } + + public Long getDelivered() + { + return _deliveredCount.get(); + } + + public synchronized void setQueue(AMQQueue queue, boolean exclusive) + { + if(getQueue() != null) + { + throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); + } + _queue = queue; + + _logSubject = new SubscriptionLogSubject(this); + _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); + + if (CurrentActor.get().getRootMessageLogger(). + isMessageEnabled(CurrentActor.get(), _logSubject, SubscriptionMessages.CREATE_LOG_HIERARCHY)) + { + // Get the string value of the filters + String filterLogString = null; + if (_filters != null && _filters.hasFilters()) + { + filterLogString = _filters.toString(); + } + + if (isAutoClose()) + { + if (filterLogString == null) + { + filterLogString = ""; + } + else + { + filterLogString += ","; + } + filterLogString += "AutoClose"; + } + + if (isBrowser()) + { + // We do not need to check for null here as all Browsers are AutoClose + filterLogString +=",Browser"; + } + + CurrentActor.get(). + message(_logSubject, + SubscriptionMessages.CREATE(filterLogString, + queue.isDurable() && exclusive, + filterLogString != null)); + } + } + + 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 entry + * @param batch + * @throws AMQException + */ + abstract public void send(QueueEntry entry, boolean batch) throws AMQException; + + + public boolean isSuspended() + { + return !isActive() || _channel.isSuspended() || _deleted.get() || _channel.getConnectionModel().isStopped(); + } + + /** + * Callback indicating that a queue has been deleted. + * + * @param queue The queue to delete + */ + public void queueDeleted(AMQQueue queue) + { + _deleted.set(true); + } + + public boolean hasInterest(QueueEntry entry) + { + //check that the message hasn't been rejected + if (entry.isRejectedBy(getSubscriptionID())) + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Subscription:" + this + " rejected message:" + entry); + } + } + + if (_noLocal) + { + AMQMessage message = (AMQMessage) entry.getMessage(); + + final Object publisherReference = message.getConnectionIdentifier(); + + // We don't want local messages so check to see if message is one we sent + Object localReference = getProtocolSession().getReference(); + + if(publisherReference != null && publisherReference.equals(localReference)) + { + return false; + } + } + + + if (_logger.isDebugEnabled()) + { + _logger.debug("(" + this + ") checking filters for message (" + entry); + } + return checkFilters(entry); + + } + + private boolean checkFilters(QueueEntry msg) + { + return (_filters == null) || _filters.allAllow(msg); + } + + 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(); + } + //Log Subscription closed + CurrentActor.get().message(_logSubject, SubscriptionMessages.CLOSE()); + } + + public boolean isClosed() + { + return getState() == State.CLOSED; + } + + + public boolean wouldSuspend(QueueEntry msg) + { + return !_creditManager.useCreditForMessage(msg.getMessage().getSize()); + } + + public boolean trySendLock() + { + return _stateChangeLock.tryLock(); + } + + public void getSendLock() + { + _stateChangeLock.lock(); + } + + public void releaseSendLock() + { + _stateChangeLock.unlock(); + } + + public AMQChannel getChannel() + { + return _channel; + } + + public AMQShortString getConsumerTag() + { + return _consumerTag; + } + + public String getConsumerName() + { + return _consumerTag == null ? null : _consumerTag.asString(); + } + + public long getSubscriptionID() + { + return _subscriptionID; + } + + public AMQProtocolSession getProtocolSession() + { + return _channel.getProtocolSession(); + } + + public LogActor getLogActor() + { + return _logActor; + } + + public AMQQueue getQueue() + { + return _queue; + } + + public void onDequeue(final QueueEntry queueEntry) + { + restoreCredit(queueEntry); + } + + public void releaseQueueEntry(final QueueEntry queueEntry) + { + restoreCredit(queueEntry); + } + + public void restoreCredit(final QueueEntry queueEntry) + { + _creditManager.restoreCredit(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); + } + } + CurrentActor.get().message(_logSubject,SubscriptionMessages.STATE(_state.get().toString())); + } + + public State getState() + { + return _state.get(); + } + + + public void setStateListener(final StateListener listener) + { + _stateListener = listener; + } + + + public AMQQueue.Context getQueueContext() + { + return _queueContext; + } + + public void setQueueContext(AMQQueue.Context context) + { + _queueContext = context; + } + + + protected void sendToClient(final QueueEntry entry, final long deliveryTag) + throws AMQException + { + _deliveryMethod.deliverToClient(this,entry,deliveryTag); + _deliveredCount.incrementAndGet(); + _deliveredBytes.addAndGet(entry.getSize()); + } + + + 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; + } + + public void confirmAutoClose() + { + ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter(); + converter.confirmConsumerAutoClose(getChannel().getChannelId(), getConsumerTag()); + } + + public boolean acquires() + { + return !isBrowser(); + } + + public boolean seesRequeues() + { + return !isBrowser(); + } + + public boolean isTransient() + { + return false; + } + + public void set(String key, Object value) + { + _properties.put(key, value); + } + + public Object get(String key) + { + return _properties.get(key); + } + + + public void setNoLocal(boolean noLocal) + { + _noLocal = noLocal; + } + + abstract boolean isBrowser(); + + public String getCreditMode() + { + return "WINDOW"; + } + + public boolean isBrowsing() + { + return isBrowser(); + } + + public boolean isExplicitAcknowledge() + { + return true; + } + + public boolean isDurable() + { + return false; + } + + public boolean isExclusive() + { + return getQueue().hasExclusiveSubscriber(); + } + + public String getName() + { + return String.valueOf(_consumerTag); + } + + public Map getArguments() + { + return null; + } + + public boolean isSessionTransactional() + { + return _channel.isTransactional(); + } + + public long getCreateTime() + { + return _createTime; + } + + public void queueEmpty() throws AMQException + { + if (isAutoClose()) + { + _queue.unregisterSubscription(this); + + confirmAutoClose(); + } + } + + public void flushBatched() + { + _channel.getProtocolSession().setDeferFlush(false); + + _channel.getProtocolSession().flushBatched(); + } + + public long getBytesOut() + { + return _deliveredBytes.longValue(); + } + + public long getMessagesOut() + { + return _deliveredCount.longValue(); + } + + + protected void addUnacknowledgedMessage(QueueEntry entry) + { + final long size = entry.getSize(); + _unacknowledgedBytes.addAndGet(size); + _unacknowledgedCount.incrementAndGet(); + entry.addStateChangeListener(new QueueEntry.StateChangeListener() + { + public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState) + { + if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED)) + { + _unacknowledgedBytes.addAndGet(-size); + _unacknowledgedCount.decrementAndGet(); + entry.removeStateChangeListener(this); + } + } + }); + } + + public long getUnacknowledgedBytes() + { + return _unacknowledgedBytes.longValue(); + } + + public long getUnacknowledgedMessages() + { + return _unacknowledgedCount.longValue(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java new file mode 100644 index 0000000000..1d41bcdcf4 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java @@ -0,0 +1,69 @@ +/* + * + * 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.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.queue.QueueEntry; + +import java.util.Collection; +import java.util.Set; + + +public interface UnacknowledgedMessageMap +{ + public interface Visitor + { + /** + * @param deliveryTag + *@param message the message being iterated over @return true to stop iteration, false to continue + * @throws AMQException + */ + boolean callback(final long deliveryTag, QueueEntry message) throws AMQException; + + void visitComplete(); + } + + void visit(Visitor visitor) throws AMQException; + + void add(long deliveryTag, QueueEntry message); + + QueueEntry remove(long deliveryTag); + + Collection cancelAllMessages(); + + int size(); + + void clear(); + + QueueEntry get(long deliveryTag); + + /** + * Get the set of delivery tags that are outstanding. + * + * @return a set of delivery tags + */ + Set getDeliveryTags(); + + Collection acknowledge(long deliveryTag, boolean multiple); + +} + + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java new file mode 100644 index 0000000000..17b2c7b985 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java @@ -0,0 +1,183 @@ +/* + * + * 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.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.queue.QueueEntry; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public class UnacknowledgedMessageMapImpl implements UnacknowledgedMessageMap +{ + private final Object _lock = new Object(); + + private long _unackedSize; + + private Map _map; + + private long _lastDeliveryTag; + + private final int _prefetchLimit; + + public UnacknowledgedMessageMapImpl(int prefetchLimit) + { + _prefetchLimit = prefetchLimit; + _map = new LinkedHashMap(prefetchLimit); + } + + public void collect(long deliveryTag, boolean multiple, Map msgs) + { + if (multiple) + { + collect(deliveryTag, msgs); + } + else + { + final QueueEntry entry = get(deliveryTag); + if(entry != null) + { + msgs.put(deliveryTag, entry); + } + } + + } + + public void remove(Map msgs) + { + synchronized (_lock) + { + for (Long deliveryTag : msgs.keySet()) + { + remove(deliveryTag); + } + } + } + + public QueueEntry remove(long deliveryTag) + { + synchronized (_lock) + { + + QueueEntry message = _map.remove(deliveryTag); + if(message != null) + { + _unackedSize -= message.getMessage().getSize(); + + } + + return message; + } + } + + public void visit(Visitor visitor) throws AMQException + { + synchronized (_lock) + { + Set> currentEntries = _map.entrySet(); + for (Map.Entry entry : currentEntries) + { + visitor.callback(entry.getKey().longValue(), entry.getValue()); + } + visitor.visitComplete(); + } + } + + public void add(long deliveryTag, QueueEntry message) + { + synchronized (_lock) + { + _map.put(deliveryTag, message); + _unackedSize += message.getMessage().getSize(); + _lastDeliveryTag = deliveryTag; + } + } + + public Collection cancelAllMessages() + { + synchronized (_lock) + { + Collection currentEntries = _map.values(); + _map = new LinkedHashMap(_prefetchLimit); + _unackedSize = 0l; + return currentEntries; + } + } + + public int size() + { + synchronized (_lock) + { + return _map.size(); + } + } + + public void clear() + { + synchronized (_lock) + { + _map.clear(); + _unackedSize = 0l; + } + } + + public QueueEntry get(long key) + { + synchronized (_lock) + { + return _map.get(key); + } + } + + public Set getDeliveryTags() + { + synchronized (_lock) + { + return _map.keySet(); + } + } + + public Collection acknowledge(long deliveryTag, boolean multiple) + { + Map ackedMessageMap = new LinkedHashMap(); + collect(deliveryTag, multiple, ackedMessageMap); + remove(ackedMessageMap); + return ackedMessageMap.values(); + } + + private void collect(long key, Map msgs) + { + synchronized (_lock) + { + for (Map.Entry entry : _map.entrySet()) + { + msgs.put(entry.getKey(),entry.getValue()); + if (entry.getKey() == key) + { + break; + } + } + } + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java new file mode 100644 index 0000000000..d805049662 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java @@ -0,0 +1,85 @@ +/* + * + * 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.v0_8.handler; + + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AccessRequestBody; +import org.apache.qpid.framing.AccessRequestOkBody; +import org.apache.qpid.framing.MethodRegistry; +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.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +/** + * @author Apache Software Foundation + * + * + */ +public class AccessRequestHandler implements StateAwareMethodListener +{ + 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(); + final AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + 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; + if(methodRegistry instanceof MethodRegistry_0_9) + { + response = ((MethodRegistry_0_9)methodRegistry).createAccessRequestOkBody(0); + } + else if(methodRegistry instanceof MethodRegistry_8_0) + { + response = ((MethodRegistry_8_0)methodRegistry).createAccessRequestOkBody(0); + } + else + { + throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9"); + } + + channel.sync(); + session.writeFrame(response.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java new file mode 100644 index 0000000000..0858598457 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java @@ -0,0 +1,67 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.BasicAckBody; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicAckMethodHandler implements StateAwareMethodListener +{ + private static final Logger _log = Logger.getLogger(BasicAckMethodHandler.class); + + private static final BasicAckMethodHandler _instance = new BasicAckMethodHandler(); + + public static BasicAckMethodHandler getInstance() + { + return _instance; + } + + private BasicAckMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, BasicAckBody body, int channelId) throws AMQException + { + AMQProtocolSession protocolSession = stateManager.getProtocolSession(); + + + if (_log.isDebugEnabled()) + { + _log.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId); + } + + final AMQChannel channel = protocolSession.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + // this method throws an AMQException if the delivery tag is not known + channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple()); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java new file mode 100644 index 0000000000..9b2efa3d03 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java @@ -0,0 +1,76 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.BasicCancelBody; +import org.apache.qpid.framing.BasicCancelOkBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicCancelMethodHandler implements StateAwareMethodListener +{ + private static final Logger _log = Logger.getLogger(BasicCancelMethodHandler.class); + + private static final BasicCancelMethodHandler _instance = new BasicCancelMethodHandler(); + + public static BasicCancelMethodHandler getInstance() + { + return _instance; + } + + private BasicCancelMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, BasicCancelBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + final AMQChannel channel = session.getChannel(channelId); + + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + if (_log.isDebugEnabled()) + { + _log.debug("BasicCancel: for:" + body.getConsumerTag() + + " nowait:" + body.getNowait()); + } + + channel.unsubscribeConsumer(body.getConsumerTag()); + if (!body.getNowait()) + { + MethodRegistry methodRegistry = session.getMethodRegistry(); + BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag()); + channel.sync(); + session.writeFrame(cancelOkBody.generateFrame(channelId)); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java new file mode 100644 index 0000000000..cfdde2c9fb --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java @@ -0,0 +1,177 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicConsumeBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class BasicConsumeMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(BasicConsumeMethodHandler.class); + + private static final BasicConsumeMethodHandler _instance = new BasicConsumeMethodHandler(); + + public static BasicConsumeMethodHandler getInstance() + { + return _instance; + } + + private BasicConsumeMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, BasicConsumeBody body, int channelId) throws AMQException + { + AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); + + AMQChannel channel = protocolConnection.getChannel(channelId); + VirtualHost vHost = protocolConnection.getVirtualHost(); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + else + { + channel.sync(); + if (_logger.isDebugEnabled()) + { + _logger.debug("BasicConsume: from '" + body.getQueue() + + "' for:" + body.getConsumerTag() + + " nowait:" + body.getNowait() + + " args:" + body.getArguments()); + } + + AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue().intern()); + + if (queue == null) + { + if (_logger.isDebugEnabled()) + { + _logger.debug("No queue for '" + body.getQueue() + "'"); + } + if (body.getQueue() != null) + { + String msg = "No such queue, '" + body.getQueue() + "'"; + throw body.getChannelException(AMQConstant.NOT_FOUND, msg); + } + else + { + String msg = "No queue name provided, no default queue defined."; + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg); + } + } + else + { + final AMQShortString consumerTagName; + + if (queue.isExclusive() && !queue.isDurable()) + { + AMQSessionModel session = queue.getExclusiveOwningSession(); + if (session == null || session.getConnectionModel() != protocolConnection) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + } + } + + if (body.getConsumerTag() != null) + { + consumerTagName = body.getConsumerTag().intern(); + } + else + { + consumerTagName = null; + } + + try + { + if(consumerTagName == null || channel.getSubscription(consumerTagName) == null) + { + + AMQShortString consumerTag = channel.subscribeToQueue(consumerTagName, queue, !body.getNoAck(), + body.getArguments(), body.getNoLocal(), body.getExclusive()); + if (!body.getNowait()) + { + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + } + } + else + { + AMQShortString msg = new AMQShortString("Non-unique consumer tag, '" + body.getConsumerTag() + "'"); + + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode + msg, // replytext + body.getClazz(), + body.getMethod()); + protocolConnection.writeFrame(responseBody.generateFrame(0)); + } + + } + catch (org.apache.qpid.AMQInvalidArgumentException ise) + { + _logger.debug("Closing connection due to invalid selector"); + + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(), + new AMQShortString(ise.getMessage()), + body.getClazz(), + body.getMethod()); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + + } + catch (AMQQueue.ExistingExclusiveSubscription e) + { + throw body.getChannelException(AMQConstant.ACCESS_REFUSED, + "Cannot subscribe to queue " + + queue.getNameShortString() + + " as it already has an existing exclusive consumer"); + } + catch (AMQQueue.ExistingSubscriptionPreventsExclusive e) + { + throw body.getChannelException(AMQConstant.ACCESS_REFUSED, + "Cannot subscribe to queue " + + queue.getNameShortString() + + " exclusively as it already has a consumer"); + } + + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java new file mode 100644 index 0000000000..9fac6d20fa --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java @@ -0,0 +1,175 @@ +/* + * 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.v0_8.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.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.flow.MessageOnlyCreditManager; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +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.protocol.v0_8.SubscriptionFactoryImpl; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class BasicGetMethodHandler implements StateAwareMethodListener +{ + 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 protocolConnection = stateManager.getProtocolSession(); + + + VirtualHost vHost = protocolConnection.getVirtualHost(); + + AMQChannel channel = protocolConnection.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + else + { + channel.sync(); + 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 + { + if (queue.isExclusive()) + { + AMQSessionModel session = queue.getExclusiveOwningSession(); + if (session == null || session.getConnectionModel() != protocolConnection) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue is exclusive, but not created on this Connection."); + } + } + + if (!performGet(queue,protocolConnection, channel, !body.getNoAck())) + { + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + // TODO - set clusterId + BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null); + + + protocolConnection.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() + { + + public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag) + throws AMQException + { + singleMessageCredit.useCreditForMessage(entry.getMessage().getSize()); + if(entry.getMessage() instanceof AMQMessage) + { + session.getProtocolOutputConverter().writeGetOk(entry, channel.getChannelId(), + deliveryTag, queue.getMessageCount()); + entry.incrementDeliveryCount(); + } + else + { + //TODO Convert AMQP 0-10 message + throw new AMQException(AMQConstant.NOT_IMPLEMENTED, "Not implemented conversion of 0-10 message", null); + } + + } + }; + 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 = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(channel, session, null, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod); + } + + queue.registerSubscription(sub,false); + queue.flushSubscription(sub); + queue.unregisterSubscription(sub); + return(!singleMessageCredit.hasCredit()); + + + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java new file mode 100644 index 0000000000..81a96a9699 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java @@ -0,0 +1,97 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicPublishBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class BasicPublishMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(BasicPublishMethodHandler.class); + + private static final BasicPublishMethodHandler _instance = new BasicPublishMethodHandler(); + + + public static BasicPublishMethodHandler getInstance() + { + return _instance; + } + + private BasicPublishMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, BasicPublishBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + if (_logger.isDebugEnabled()) + { + _logger.debug("Publish received on channel " + channelId); + } + + AMQShortString exchangeName = body.getExchange(); + // TODO: check the delivery tag field details - is it unique across the broker or per subscriber? + if (exchangeName == null) + { + exchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME; + } + + VirtualHost vHost = session.getVirtualHost(); + Exchange exch = vHost.getExchange(exchangeName.toString()); + // if the exchange does not exist we raise a channel exception + if (exch == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name"); + } + else + { + // The partially populated BasicDeliver frame plus the received route body + // is stored in the channel. Once the final body frame has been received + // it is routed to the exchange. + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + MessagePublishInfo info = session.getMethodRegistry().getProtocolVersionMethodConverter().convertToInfo(body); + info.setExchange(exchangeName); + channel.setPublishFrame(info, exch); + } + } + +} + + + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java new file mode 100644 index 0000000000..85f85b3677 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java @@ -0,0 +1,58 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.BasicQosBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicQosHandler implements StateAwareMethodListener +{ + private static final BasicQosHandler _instance = new BasicQosHandler(); + + public static BasicQosHandler getInstance() + { + return _instance; + } + + public void methodReceived(AMQStateManager stateManager, BasicQosBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.sync(); + channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount()); + + + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java new file mode 100644 index 0000000000..7ce8316c94 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.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.protocol.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.BasicRecoverBody; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicRecoverMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(BasicRecoverMethodHandler.class); + + private static final BasicRecoverMethodHandler _instance = new BasicRecoverMethodHandler(); + + public static BasicRecoverMethodHandler getInstance() + { + return _instance; + } + + public void methodReceived(AMQStateManager stateManager, BasicRecoverBody 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.v8_0)) + { + MethodRegistry_8_0 methodRegistry = (MethodRegistry_8_0) session.getMethodRegistry(); + AMQMethodBody recoverOk = methodRegistry.createBasicRecoverOkBody(); + channel.sync(); + session.writeFrame(recoverOk.generateFrame(channelId)); + + } + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java new file mode 100644 index 0000000000..bf8565b3f2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.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.protocol.v0_8.handler; + + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.BasicRecoverSyncBody; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; +import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener +{ + 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.sync(); + 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)); + + } + else if(session.getProtocolVersion().equals(ProtocolVersion.v0_91)) + { + MethodRegistry_0_91 methodRegistry = (MethodRegistry_0_91) session.getMethodRegistry(); + AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody(); + session.writeFrame(recoverOk.generateFrame(channelId)); + + } + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java new file mode 100644 index 0000000000..40619a5879 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java @@ -0,0 +1,139 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.BasicRejectBody; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class BasicRejectMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(BasicRejectMethodHandler.class); + + private static BasicRejectMethodHandler _instance = new BasicRejectMethodHandler(); + + public static BasicRejectMethodHandler getInstance() + { + return _instance; + } + + private BasicRejectMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, BasicRejectBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + if (_logger.isDebugEnabled()) + { + _logger.debug("Rejecting:" + body.getDeliveryTag() + + ": Requeue:" + body.getRequeue() + + " on channel:" + channel.debugIdentity()); + } + + long deliveryTag = body.getDeliveryTag(); + + QueueEntry message = channel.getUnacknowledgedMessageMap().get(deliveryTag); + + if (message == null) + { + _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag); + } + else + { + if (message.isQueueDeleted()) + { + _logger.warn("Message's Queue has already been purged, dropping message"); + message = channel.getUnacknowledgedMessageMap().remove(deliveryTag); + if(message != null) + { + message.discard(); + } + return; + } + + if (message.getMessage() == null) + { + _logger.warn("Message has already been purged, unable to Reject."); + return; + } + + + if (_logger.isDebugEnabled()) + { + _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() + + ": Requeue:" + body.getRequeue() + + " on channel:" + channel.debugIdentity()); + } + + message.reject(); + + if (body.getRequeue()) + { + channel.requeue(deliveryTag); + + //this requeue represents a message rejected from the pre-dispatch queue + //therefore we need to amend the delivery counter. + message.decrementDeliveryCount(); + } + else + { + final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag); + _logger.debug("maxDeliveryCountEnabled: " + maxDeliveryCountEnabled + " deliveryTag " + deliveryTag); + if (maxDeliveryCountEnabled) + { + final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag); + _logger.debug("deliveredTooManyTimes: " + deliveredTooManyTimes + " deliveryTag " + deliveryTag); + if (deliveredTooManyTimes) + { + channel.deadLetter(body.getDeliveryTag()); + } + else + { + //this requeue represents a message rejected because of a recover/rollback that we + //are not ready to DLQ. We rely on the reject command to resend from the unacked map + //and therefore need to increment the delivery counter so we cancel out the effect + //of the AMQChannel#resend() decrement. + message.incrementDeliveryCount(); + } + } + else + { + channel.deadLetter(body.getDeliveryTag()); + } + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java new file mode 100644 index 0000000000..6ff5d80048 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java @@ -0,0 +1,76 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ChannelCloseBody; +import org.apache.qpid.framing.ChannelCloseOkBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ChannelCloseHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ChannelCloseHandler.class); + + private static ChannelCloseHandler _instance = new ChannelCloseHandler(); + + public static ChannelCloseHandler getInstance() + { + return _instance; + } + + private ChannelCloseHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ChannelCloseBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + if (_logger.isInfoEnabled()) + { + _logger.info("Received channel close for id " + channelId + " citing class " + body.getClassId() + + " and method " + body.getMethodId()); + } + + + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getConnectionException(AMQConstant.CHANNEL_ERROR, "Trying to close unknown channel"); + } + channel.sync(); + session.closeChannel(channelId); + // Client requested closure so we don't wait for ok we send it + stateManager.getProtocolSession().closeChannelOk(channelId); + + MethodRegistry methodRegistry = session.getMethodRegistry(); + ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java new file mode 100644 index 0000000000..2a220ff78d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java @@ -0,0 +1,53 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ChannelCloseOkBody; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ChannelCloseOkHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ChannelCloseOkHandler.class); + + private static ChannelCloseOkHandler _instance = new ChannelCloseOkHandler(); + + public static ChannelCloseOkHandler getInstance() + { + return _instance; + } + + private ChannelCloseOkHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ChannelCloseOkBody body, int channelId) throws AMQException + { + + _logger.info("Received channel-close-ok for channel-id " + channelId); + + // Let the Protocol Session know the channel is now closed. + stateManager.getProtocolSession().closeChannelOk(channelId); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java new file mode 100644 index 0000000000..e29c22f25f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java @@ -0,0 +1,68 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.ChannelFlowBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ChannelFlowHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ChannelFlowHandler.class); + + private static ChannelFlowHandler _instance = new ChannelFlowHandler(); + + public static ChannelFlowHandler getInstance() + { + return _instance; + } + + private ChannelFlowHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ChannelFlowBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.sync(); + channel.setSuspended(!body.getActive()); + _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive()); + + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive()); + session.writeFrame(responseBody.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java new file mode 100644 index 0000000000..7d47efbc8b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java @@ -0,0 +1,142 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ChannelOpenBody; +import org.apache.qpid.framing.ChannelOpenOkBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; +import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; +import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.UUID; + +public class ChannelOpenHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ChannelOpenHandler.class); + + private static ChannelOpenHandler _instance = new ChannelOpenHandler(); + + public static ChannelOpenHandler getInstance() + { + return _instance; + } + + private ChannelOpenHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ChannelOpenBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + VirtualHost virtualHost = session.getVirtualHost(); + + // Protect the broker against out of order frame request. + if (virtualHost == null) + { + throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null); + } + _logger.info("Connecting to: " + virtualHost.getName()); + + final AMQChannel channel = new AMQChannel(session,channelId, virtualHost.getMessageStore()); + + session.addChannel(channel); + + ChannelOpenOkBody response; + + ProtocolVersion pv = session.getProtocolVersion(); + + if(pv.equals(ProtocolVersion.v8_0)) + { + MethodRegistry_8_0 methodRegistry = (MethodRegistry_8_0) MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0); + response = methodRegistry.createChannelOpenOkBody(); + + } + else if(pv.equals(ProtocolVersion.v0_9)) + { + MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); + UUID uuid = UUID.randomUUID(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + DataOutputStream dataOut = new DataOutputStream(output); + try + { + dataOut.writeLong(uuid.getMostSignificantBits()); + dataOut.writeLong(uuid.getLeastSignificantBits()); + dataOut.flush(); + dataOut.close(); + } + catch (IOException e) + { + // This *really* shouldn't happen as we're not doing any I/O + throw new RuntimeException("I/O exception when writing to byte array", e); + } + + // should really associate this channelId to the session + byte[] channelName = output.toByteArray(); + + response = methodRegistry.createChannelOpenOkBody(channelName); + } + else if(pv.equals(ProtocolVersion.v0_91)) + { + MethodRegistry_0_91 methodRegistry = (MethodRegistry_0_91) MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91); + UUID uuid = UUID.randomUUID(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + DataOutputStream dataOut = new DataOutputStream(output); + try + { + dataOut.writeLong(uuid.getMostSignificantBits()); + dataOut.writeLong(uuid.getLeastSignificantBits()); + dataOut.flush(); + dataOut.close(); + } + catch (IOException e) + { + // This *really* shouldn't happen as we're not doing any I/O + throw new RuntimeException("I/O exception when writing to byte array", e); + } + + // should really associate this channelId to the session + byte[] channelName = output.toByteArray(); + + response = methodRegistry.createChannelOpenOkBody(channelName); + } + else + { + throw new AMQException(AMQConstant.INTERNAL_ERROR, "Got channel open for protocol version not catered for: " + pv, null); + } + + + session.writeFrame(response.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java new file mode 100644 index 0000000000..b530b8a188 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java @@ -0,0 +1,72 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ConnectionCloseOkBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ConnectionCloseMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionCloseMethodHandler.class); + + private static ConnectionCloseMethodHandler _instance = new ConnectionCloseMethodHandler(); + + public static ConnectionCloseMethodHandler getInstance() + { + return _instance; + } + + private ConnectionCloseMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ConnectionCloseBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + if (_logger.isInfoEnabled()) + { + _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" + + body.getReplyText() + " for " + session); + } + try + { + session.closeSession(); + } + catch (Exception e) + { + _logger.error("Error closing protocol session: " + e, e); + } + + MethodRegistry methodRegistry = session.getMethodRegistry(); + ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + + session.closeProtocolSession(); + + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java new file mode 100644 index 0000000000..6b80a2c17e --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java @@ -0,0 +1,63 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ConnectionCloseOkBody; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ConnectionCloseOkMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionCloseOkMethodHandler.class); + + private static ConnectionCloseOkMethodHandler _instance = new ConnectionCloseOkMethodHandler(); + + public static ConnectionCloseOkMethodHandler getInstance() + { + return _instance; + } + + private ConnectionCloseOkMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ConnectionCloseOkBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + //todo should this not do more than just log the method? + _logger.info("Received Connection-close-ok"); + + try + { + stateManager.changeState(AMQState.CONNECTION_CLOSED); + session.closeSession(); + } + catch (Exception e) + { + _logger.error("Error closing protocol session: " + e, e); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java new file mode 100644 index 0000000000..286f58e1b3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java @@ -0,0 +1,107 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ConnectionOpenBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.State; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class ConnectionOpenMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionOpenMethodHandler.class); + + private static ConnectionOpenMethodHandler _instance = new ConnectionOpenMethodHandler(); + + public static ConnectionOpenMethodHandler getInstance() + { + return _instance; + } + + private ConnectionOpenMethodHandler() + { + } + + private static AMQShortString generateClientID() + { + return new AMQShortString(Long.toString(System.currentTimeMillis())); + } + + public void methodReceived(AMQStateManager stateManager, ConnectionOpenBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + //ignore leading '/' + String virtualHostName; + if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/') + { + virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString(); + } + else + { + virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost()); + } + + VirtualHost virtualHost = stateManager.getVirtualHostRegistry().getVirtualHost(virtualHostName); + + if (virtualHost == null) + { + throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'"); + } + else + { + // Check virtualhost access + if (!virtualHost.getSecurityManager().accessVirtualhost(virtualHostName, session.getRemoteAddress())) + { + throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied: '" + virtualHost.getName() + "'"); + } + else if (virtualHost.getState() != State.ACTIVE) + { + throw body.getConnectionException(AMQConstant.CONNECTION_FORCED, "Virtual host '" + virtualHost.getName() + "' is not active"); + } + + session.setVirtualHost(virtualHost); + + // See Spec (0.8.2). Section 3.1.2 Virtual Hosts + if (session.getContextKey() == null) + { + session.setContextKey(generateClientID()); + } + + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost()); + + stateManager.changeState(AMQState.CONNECTION_OPEN); + + session.writeFrame(responseBody.generateFrame(channelId)); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java new file mode 100644 index 0000000000..628a6b40c3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java @@ -0,0 +1,132 @@ +/* + * + * 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.v0_8.handler; + + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ConnectionSecureBody; +import org.apache.qpid.framing.ConnectionSecureOkBody; +import org.apache.qpid.framing.ConnectionTuneBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionSecureOkMethodHandler.class); + + private static ConnectionSecureOkMethodHandler _instance = new ConnectionSecureOkMethodHandler(); + + public static ConnectionSecureOkMethodHandler getInstance() + { + return _instance; + } + + private ConnectionSecureOkMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ConnectionSecureOkBody body, int channelId) throws AMQException + { + Broker broker = stateManager.getBroker(); + AMQProtocolSession session = stateManager.getProtocolSession(); + + SubjectCreator subjectCreator = stateManager.getSubjectCreator(); + + SaslServer ss = session.getSaslServer(); + if (ss == null) + { + throw new AMQException("No SASL context set up in session"); + } + MethodRegistry methodRegistry = session.getMethodRegistry(); + SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); + switch (authResult.getStatus()) + { + case ERROR: + 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(), + AMQConstant.NOT_ALLOWED.getName(), + body.getClazz(), + body.getMethod()); + + session.writeFrame(connectionCloseBody.generateFrame(0)); + disposeSaslServer(session); + break; + case SUCCESS: + if (_logger.isInfoEnabled()) + { + _logger.info("Connected as: " + authResult.getSubject()); + } + stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); + + ConnectionTuneBody tuneBody = + methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT), + BrokerProperties.FRAME_SIZE, + (Integer)broker.getAttribute(Broker.CONNECTION_HEART_BEAT_DELAY)); + session.writeFrame(tuneBody.generateFrame(0)); + session.setAuthorizedSubject(authResult.getSubject()); + disposeSaslServer(session); + break; + case CONTINUE: + stateManager.changeState(AMQState.CONNECTION_NOT_AUTH); + + ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge()); + session.writeFrame(secureBody.generateFrame(0)); + } + } + + private void disposeSaslServer(AMQProtocolSession ps) + { + SaslServer ss = ps.getSaslServer(); + if (ss != null) + { + ps.setSaslServer(null); + try + { + ss.dispose(); + } + catch (SaslException e) + { + _logger.error("Error disposing of Sasl server: " + e); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java new file mode 100644 index 0000000000..1ffbf046d2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java @@ -0,0 +1,154 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.ConnectionSecureBody; +import org.apache.qpid.framing.ConnectionStartOkBody; +import org.apache.qpid.framing.ConnectionTuneBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + + +public class ConnectionStartOkMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionStartOkMethodHandler.class); + + private static ConnectionStartOkMethodHandler _instance = new ConnectionStartOkMethodHandler(); + + public static ConnectionStartOkMethodHandler getInstance() + { + return _instance; + } + + private ConnectionStartOkMethodHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException + { + Broker broker = stateManager.getBroker(); + AMQProtocolSession session = stateManager.getProtocolSession(); + + _logger.info("SASL Mechanism selected: " + body.getMechanism()); + _logger.info("Locale selected: " + body.getLocale()); + + SubjectCreator subjectCreator = stateManager.getSubjectCreator(); + SaslServer ss = null; + try + { + ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal()); + + if (ss == null) + { + throw body.getConnectionException(AMQConstant.RESOURCE_ERROR, "Unable to create SASL Server:" + body.getMechanism()); + } + + session.setSaslServer(ss); + + final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); + //save clientProperties + session.setClientProperties(body.getClientProperties()); + + MethodRegistry methodRegistry = session.getMethodRegistry(); + + switch (authResult.getStatus()) + { + case ERROR: + Exception cause = authResult.getCause(); + + _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage())); + + stateManager.changeState(AMQState.CONNECTION_CLOSING); + + ConnectionCloseBody closeBody = + methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode + AMQConstant.NOT_ALLOWED.getName(), + body.getClazz(), + body.getMethod()); + + session.writeFrame(closeBody.generateFrame(0)); + disposeSaslServer(session); + break; + + case SUCCESS: + if (_logger.isInfoEnabled()) + { + _logger.info("Connected as: " + authResult.getSubject()); + } + session.setAuthorizedSubject(authResult.getSubject()); + + stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); + + ConnectionTuneBody tuneBody = methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT), + BrokerProperties.FRAME_SIZE, + (Integer)broker.getAttribute(Broker.CONNECTION_HEART_BEAT_DELAY)); + session.writeFrame(tuneBody.generateFrame(0)); + break; + case CONTINUE: + stateManager.changeState(AMQState.CONNECTION_NOT_AUTH); + + ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge()); + session.writeFrame(secureBody.generateFrame(0)); + } + } + catch (SaslException e) + { + disposeSaslServer(session); + throw new AMQException("SASL error: " + e, e); + } + } + + private void disposeSaslServer(AMQProtocolSession ps) + { + SaslServer ss = ps.getSaslServer(); + if (ss != null) + { + ps.setSaslServer(null); + try + { + ss.dispose(); + } + catch (SaslException e) + { + _logger.error("Error disposing of Sasl server: " + e); + } + } + } + +} + + + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.java new file mode 100644 index 0000000000..bc98bbad2d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.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.server.protocol.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ConnectionTuneOkBody; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ConnectionTuneOkMethodHandler.class); + + private static ConnectionTuneOkMethodHandler _instance = new ConnectionTuneOkMethodHandler(); + + public static ConnectionTuneOkMethodHandler getInstance() + { + return _instance; + } + + public void methodReceived(AMQStateManager stateManager, ConnectionTuneOkBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + if (_logger.isDebugEnabled()) + { + _logger.debug(body); + } + stateManager.changeState(AMQState.CONNECTION_NOT_OPENED); + session.initHeartbeats(body.getHeartbeat()); + session.setMaxFrameSize(body.getFrameMax()); + + long maxChannelNumber = body.getChannelMax(); + //0 means no implied limit, except that forced by protocol limitations (0xFFFF) + session.setMaximumNumberOfChannels( maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java new file mode 100644 index 0000000000..ac5a64f48a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java @@ -0,0 +1,192 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ExchangeBoundBody; +import org.apache.qpid.framing.ExchangeBoundOkBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +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.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +/** + * @author Apache Software Foundation + * + * + */ +public class ExchangeBoundHandler implements StateAwareMethodListener +{ + private static final ExchangeBoundHandler _instance = new ExchangeBoundHandler(); + + public static final int OK = 0; + + public static final int EXCHANGE_NOT_FOUND = 1; + + public static final int QUEUE_NOT_FOUND = 2; + + public static final int NO_BINDINGS = 3; + + public static final int QUEUE_NOT_BOUND = 4; + + public static final int NO_QUEUE_BOUND_WITH_RK = 5; + + public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6; + + public static ExchangeBoundHandler getInstance() + { + return _instance; + } + + private ExchangeBoundHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ExchangeBoundBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + VirtualHost virtualHost = session.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + MethodRegistry methodRegistry = session.getMethodRegistry(); + + final AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.sync(); + + + AMQShortString exchangeName = body.getExchange(); + AMQShortString queueName = body.getQueue(); + AMQShortString routingKey = body.getRoutingKey(); + if (exchangeName == null) + { + throw new AMQException("Exchange exchange must not be null"); + } + Exchange exchange = virtualHost.getExchange(exchangeName.toString()); + ExchangeBoundOkBody response; + if (exchange == null) + { + + + response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND, + new AMQShortString("Exchange " + exchangeName + " not found")); + } + else if (routingKey == null) + { + if (queueName == null) + { + if (exchange.hasBindings()) + { + response = methodRegistry.createExchangeBoundOkBody(OK, null); + } + else + { + + response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS, // replyCode + null); // replyText + } + } + else + { + + AMQQueue queue = queueRegistry.getQueue(queueName); + if (queue == null) + { + + response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode + new AMQShortString("Queue " + queueName + " not found")); // replyText + } + else + { + if (exchange.isBound(queue)) + { + + response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode + null); // replyText + } + else + { + + response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND, // replyCode + new AMQShortString("Queue " + queueName + " not bound to exchange " + exchangeName)); // replyText + } + } + } + } + else if (queueName != null) + { + AMQQueue queue = queueRegistry.getQueue(queueName); + if (queue == null) + { + + response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode + new AMQShortString("Queue " + queueName + " not found")); // replyText + } + else + { + if (exchange.isBound(body.getRoutingKey(), queue)) + { + + response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode + null); // replyText + } + else + { + + String message = "Queue " + queueName + " not bound with routing key " + + body.getRoutingKey() + " to exchange " + exchangeName; + + if(message.length()>255) + { + message = message.substring(0,254); + } + response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, // replyCode + new AMQShortString(message)); // replyText + } + } + } + else + { + if (exchange.isBound(body.getRoutingKey())) + { + + response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode + null); // replyText + } + else + { + + response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK, // replyCode + new AMQShortString("No queue bound with routing key " + body.getRoutingKey() + + " to exchange " + exchangeName)); // replyText + } + } + session.writeFrame(response.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.java new file mode 100644 index 0000000000..7f8fbe1cdc --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.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.server.protocol.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQConnectionException; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQUnknownExchangeType; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ExchangeDeclareBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.ExchangeExistsException; +import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class ExchangeDeclareHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(ExchangeDeclareHandler.class); + + private static final ExchangeDeclareHandler _instance = new ExchangeDeclareHandler(); + + public static ExchangeDeclareHandler getInstance() + { + return _instance; + } + + private ExchangeDeclareHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ExchangeDeclareBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + VirtualHost virtualHost = session.getVirtualHost(); + final AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + final AMQShortString exchangeName = body.getExchange(); + if (_logger.isDebugEnabled()) + { + _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName); + } + + Exchange exchange; + + if (body.getPassive()) + { + exchange = virtualHost.getExchange(exchangeName == null ? null : exchangeName.toString()); + if(exchange == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName); + } + else if (!exchange.getTypeShortString().equals(body.getType()) && !(body.getType() == null || body.getType().length() ==0)) + { + + throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + + exchangeName + " of type " + exchange.getTypeShortString() + + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null); + } + + } + else + { + try + { + exchange = virtualHost.createExchange(null, + exchangeName == null ? null : exchangeName.intern().toString(), + body.getType() == null ? null : body.getType().intern().toString(), + body.getDurable(), + body.getAutoDelete(), + null); + + } + catch(ReservedExchangeNameException e) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Attempt to declare exchange: " + exchangeName + + " which begins with reserved prefix."); + + } + catch(ExchangeExistsException e) + { + exchange = e.getExistingExchange(); + if(!exchange.getTypeShortString().equals(body.getType())) + { + throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + + exchangeName + " of type " + + exchange.getTypeShortString() + + " to " + body.getType() +".", + body.getClazz(), body.getMethod(), + body.getMajor(), body.getMinor(),null); + } + } + catch(AMQUnknownExchangeType e) + { + throw body.getConnectionException(AMQConstant.COMMAND_INVALID, "Unknown exchange: " + exchangeName,e); + } + } + + + if(!body.getNowait()) + { + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody(); + channel.sync(); + session.writeFrame(responseBody.generateFrame(channelId)); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java new file mode 100644 index 0000000000..e0fe3d7493 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java @@ -0,0 +1,92 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.ExchangeDeleteBody; +import org.apache.qpid.framing.ExchangeDeleteOkBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeInUseException; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; +import org.apache.qpid.server.virtualhost.RequiredExchangeException; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class ExchangeDeleteHandler implements StateAwareMethodListener +{ + private static final ExchangeDeleteHandler _instance = new ExchangeDeleteHandler(); + + public static ExchangeDeleteHandler getInstance() + { + return _instance; + } + + private ExchangeDeleteHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, ExchangeDeleteBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + VirtualHost virtualHost = session.getVirtualHost(); + final AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.sync(); + try + { + final String exchangeName = body.getExchange() == null ? null : body.getExchange().toString(); + + final Exchange exchange = virtualHost.getExchange(exchangeName); + if(exchange == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange()); + } + + virtualHost.removeExchange(exchange, !body.getIfUnused()); + + ExchangeDeleteOkBody responseBody = session.getMethodRegistry().createExchangeDeleteOkBody(); + + session.writeFrame(responseBody.generateFrame(channelId)); + } + catch (ExchangeInUseException e) + { + throw body.getChannelException(AMQConstant.IN_USE, "Exchange in use"); + // TODO: sort out consistent channel close mechanism that does all clean up etc. + } + + catch (ExchangeIsAlternateException e) + { + throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange"); + + } + catch (RequiredExchangeException e) + { + throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange '"+body.getExchange()+"' cannot be deleted"); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.java new file mode 100644 index 0000000000..6ff511ea30 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.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.protocol.v0_8.handler; + +import java.util.concurrent.Executor; + +/** + * An executor that executes the task on the current thread. + */ +public class OnCurrentThreadExecutor implements Executor +{ + public void execute(Runnable command) + { + command.run(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java new file mode 100644 index 0000000000..62706d8c5d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java @@ -0,0 +1,159 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueueBindBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; + +public class QueueBindHandler implements StateAwareMethodListener +{ + private static final Logger _log = Logger.getLogger(QueueBindHandler.class); + + private static final QueueBindHandler _instance = new QueueBindHandler(); + + public static QueueBindHandler getInstance() + { + return _instance; + } + + private QueueBindHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, QueueBindBody body, int channelId) throws AMQException + { + AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); + VirtualHost virtualHost = protocolConnection.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + final AMQQueue queue; + final AMQShortString routingKey; + + if (body.getQueue() == null) + { + + queue = channel.getDefaultQueue(); + + if (queue == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "No default queue defined on channel and queue was null"); + } + + if (body.getRoutingKey() == null) + { + routingKey = queue.getNameShortString(); + } + else + { + routingKey = body.getRoutingKey().intern(); + } + } + else + { + queue = queueRegistry.getQueue(body.getQueue()); + routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern(); + } + + if (queue == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); + } + final String exchangeName = body.getExchange() == null ? null : body.getExchange().toString(); + final Exchange exch = virtualHost.getExchange(exchangeName); + if (exch == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist."); + } + + + try + { + if (queue.isExclusive() && !queue.isDurable()) + { + AMQSessionModel session = queue.getExclusiveOwningSession(); + if (session == null || session.getConnectionModel() != protocolConnection) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + } + } + + if (!exch.isBound(routingKey, body.getArguments(), queue)) + { + String bindingKey = String.valueOf(routingKey); + Map arguments = FieldTable.convertToMap(body.getArguments()); + + if(!exch.addBinding(bindingKey, queue, arguments)) + { + Binding oldBinding = exch.getBinding(bindingKey, queue, arguments); + + Map oldArgs = oldBinding.getArguments(); + if((oldArgs == null && !arguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(arguments))) + { + exch.replaceBinding(oldBinding.getId(), bindingKey, queue, arguments); + } + } + } + } + catch (AMQException e) + { + throw body.getChannelException(AMQConstant.CHANNEL_ERROR, e.toString()); + } + + if (_log.isInfoEnabled()) + { + _log.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey); + } + if (!body.getNowait()) + { + channel.sync(); + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody(); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java new file mode 100644 index 0000000000..3f582a6d73 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.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.server.protocol.v0_8.handler; + +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.framing.MethodRegistry; +import org.apache.qpid.framing.QueueDeclareBody; +import org.apache.qpid.framing.QueueDeclareOkBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; +import java.util.UUID; + +public class QueueDeclareHandler implements StateAwareMethodListener +{ + private static final Logger _logger = Logger.getLogger(QueueDeclareHandler.class); + + private static final QueueDeclareHandler _instance = new QueueDeclareHandler(); + + public static QueueDeclareHandler getInstance() + { + return _instance; + } + + public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException + { + final AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); + final AMQSessionModel session = protocolConnection.getChannel(channelId); + VirtualHost virtualHost = protocolConnection.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + + final AMQShortString queueName; + + // if we aren't given a queue name, we create one which we return to the client + if ((body.getQueue() == null) || (body.getQueue().length() == 0)) + { + queueName = createName(); + } + else + { + queueName = body.getQueue().intern(); + } + + AMQQueue queue; + + //TODO: do we need to check that the queue already exists with exactly the same "configuration"? + + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + synchronized (queueRegistry) + { + queue = queueRegistry.getQueue(queueName); + + AMQSessionModel owningSession = null; + + if (queue != null) + { + owningSession = queue.getExclusiveOwningSession(); + } + + if (queue == null) + { + if (body.getPassive()) + { + String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; + throw body.getChannelException(AMQConstant.NOT_FOUND, msg); + } + else + { + queue = createQueue(queueName, body, virtualHost, protocolConnection); + queue.setAuthorizationHolder(protocolConnection); + if (queue.isDurable() && !queue.isAutoDelete()) + { + DurableConfigurationStoreHelper.createQueue(store, queue, body.getArguments()); + } + if(body.getAutoDelete()) + { + queue.setDeleteOnNoConsumers(true); + } + queueRegistry.registerQueue(queue); + if (body.getExclusive()) + { + queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId)); + queue.setAuthorizationHolder(protocolConnection); + + if(!body.getDurable()) + { + final AMQQueue q = queue; + final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task() + { + public void doTask(AMQProtocolSession session) throws AMQException + { + q.setExclusiveOwningSession(null); + } + }; + protocolConnection.addSessionCloseTask(sessionCloseTask); + queue.addQueueDeleteTask(new AMQQueue.Task() { + public void doTask(AMQQueue queue) throws AMQException + { + protocolConnection.removeSessionCloseTask(sessionCloseTask); + } + }); + } + } + } + } + else if (queue.isExclusive() && !queue.isDurable() && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + } + else if(!body.getPassive() && ((queue.isExclusive()) != body.getExclusive())) + { + + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different exclusivity (was: " + + queue.isExclusive() + " requested " + body.getExclusive() + ")"); + } + else if (!body.getPassive() && body.getExclusive() && !(queue.isDurable() ? String.valueOf(queue.getOwner()).equals(session.getClientID()) : (owningSession == null || owningSession.getConnectionModel() == protocolConnection))) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "'), " + + "as exclusive queue with same name " + + "declared on another client ID('" + + queue.getOwner() + "') your clientID('" + session.getClientID() + "')"); + + } + else if(!body.getPassive() && queue.isAutoDelete() != body.getAutoDelete()) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different auto-delete (was: " + + queue.isAutoDelete() + " requested " + body.getAutoDelete() + ")"); + } + else if(!body.getPassive() && queue.isDurable() != body.getDurable()) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different durability (was: " + + queue.isDurable() + " requested " + body.getDurable() + ")"); + } + + + + //set this as the default queue on the channel: + channel.setDefaultQueue(queue); + } + + if (!body.getNowait()) + { + channel.sync(); + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + QueueDeclareOkBody responseBody = + methodRegistry.createQueueDeclareOkBody(queueName, + queue.getMessageCount(), + queue.getConsumerCount()); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + _logger.info("Queue " + queueName + " declared successfully"); + } + } + + protected AMQShortString createName() + { + return new AMQShortString("tmp_" + UUID.randomUUID()); + } + + protected AMQQueue createQueue(final AMQShortString queueName, + QueueDeclareBody body, + VirtualHost virtualHost, + final AMQProtocolSession session) + throws AMQException + { + final QueueRegistry registry = virtualHost.getQueueRegistry(); + String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null; + + Map arguments = FieldTable.convertToMap(body.getArguments()); + String queueNameString = AMQShortString.toString(queueName); + + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()), + queueNameString, body.getDurable(), owner, body.getAutoDelete(), + body.getExclusive(),virtualHost, arguments); + + if (body.getExclusive() && !body.getDurable()) + { + final AMQProtocolSession.Task deleteQueueTask = + new AMQProtocolSession.Task() + { + public void doTask(AMQProtocolSession session) throws AMQException + { + if (registry.getQueue(queueName) == queue) + { + queue.delete(); + } + } + }; + + session.addSessionCloseTask(deleteQueueTask); + + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) + { + session.removeSessionCloseTask(deleteQueueTask); + } + }); + } + + return queue; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java new file mode 100644 index 0000000000..d6cac50a5d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java @@ -0,0 +1,128 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueueDeleteBody; +import org.apache.qpid.framing.QueueDeleteOkBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class QueueDeleteHandler implements StateAwareMethodListener +{ + private static final QueueDeleteHandler _instance = new QueueDeleteHandler(); + + public static QueueDeleteHandler getInstance() + { + return _instance; + } + + private final boolean _failIfNotFound; + + public QueueDeleteHandler() + { + this(true); + } + + public QueueDeleteHandler(boolean failIfNotFound) + { + _failIfNotFound = failIfNotFound; + + } + + public void methodReceived(AMQStateManager stateManager, QueueDeleteBody body, int channelId) throws AMQException + { + AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); + VirtualHost virtualHost = protocolConnection.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); + + + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.sync(); + AMQQueue queue; + if (body.getQueue() == null) + { + + //get the default queue on the channel: + queue = channel.getDefaultQueue(); + } + else + { + queue = queueRegistry.getQueue(body.getQueue()); + } + + if (queue == null) + { + if (_failIfNotFound) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); + } + } + else + { + if (body.getIfEmpty() && !queue.isEmpty()) + { + throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty."); + } + else if (body.getIfUnused() && !queue.isUnused()) + { + // TODO - Error code + throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used."); + } + else + { + AMQSessionModel session = queue.getExclusiveOwningSession(); + if (queue.isExclusive() && !queue.isDurable() && (session == null || session.getConnectionModel() != protocolConnection)) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + } + + int purged = queue.delete(); + + if (queue.isDurable()) + { + DurableConfigurationStoreHelper.removeQueue(store, queue); + } + + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.java new file mode 100644 index 0000000000..ff4425b8f7 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.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.protocol.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueuePurgeBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class QueuePurgeHandler implements StateAwareMethodListener +{ + 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 protocolConnection = stateManager.getProtocolSession(); + VirtualHost virtualHost = protocolConnection.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + + AMQChannel channel = protocolConnection.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + AMQQueue queue; + if(body.getQueue() == null) + { + + //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 + { + AMQSessionModel session = queue.getExclusiveOwningSession(); + + if (queue.isExclusive() && (session == null || session.getConnectionModel() != protocolConnection)) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue is exclusive, but not created on this Connection."); + } + + long purged = queue.clearQueue(); + + + if(!body.getNowait()) + { + channel.sync(); + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.java new file mode 100644 index 0000000000..f5d7a49915 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.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.server.protocol.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueueUnbindBody; +import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; +import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +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.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class QueueUnbindHandler implements StateAwareMethodListener +{ + private static final Logger _log = Logger.getLogger(QueueUnbindHandler.class); + + private static final QueueUnbindHandler _instance = new QueueUnbindHandler(); + + public static QueueUnbindHandler getInstance() + { + return _instance; + } + + private QueueUnbindHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, QueueUnbindBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + VirtualHost virtualHost = session.getVirtualHost(); + QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); + + + final AMQQueue queue; + final AMQShortString routingKey; + + + AMQChannel channel = session.getChannel(channelId); + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + if (body.getQueue() == null) + { + + queue = channel.getDefaultQueue(); + + if (queue == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "No default queue defined on channel and queue was null"); + } + + routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); + + } + else + { + queue = queueRegistry.getQueue(body.getQueue()); + routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); + } + + if (queue == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); + } + final Exchange exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString()); + if (exch == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist."); + } + + if(exch.getBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(body.getArguments())) == null) + { + throw body.getChannelException(AMQConstant.NOT_FOUND,"No such binding"); + } + else + { + exch.removeBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(body.getArguments())); + } + + + if (_log.isInfoEnabled()) + { + _log.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey); + } + + final MethodRegistry registry = session.getMethodRegistry(); + final AMQMethodBody responseBody; + if (registry instanceof MethodRegistry_0_9) + { + responseBody = ((MethodRegistry_0_9)registry).createQueueUnbindOkBody(); + } + else if (registry instanceof MethodRegistry_0_91) + { + responseBody = ((MethodRegistry_0_91)registry).createQueueUnbindOkBody(); + } + else + { + // 0-8 does not support QueueUnbind + throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + session.getProtocolVersion(), null); + } + channel.sync(); + session.writeFrame(responseBody.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java new file mode 100644 index 0000000000..43e97c0cb6 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java @@ -0,0 +1,574 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.*; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; + +import java.util.HashMap; +import java.util.Map; + +public class ServerMethodDispatcherImpl implements MethodDispatcher +{ + private final AMQStateManager _stateManager; + + private static interface DispatcherFactory + { + public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager); + } + + private static final Map _dispatcherFactories = + new HashMap(); + + + 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); + } + }); + _dispatcherFactories.put(ProtocolVersion.v0_91, + new DispatcherFactory() + { + public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager) + { + return new ServerMethodDispatcherImpl_0_91(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/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java new file mode 100644 index 0000000000..1ee6d732c2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java @@ -0,0 +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.protocol.v0_8.handler; + + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.*; +import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; + + + +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/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java new file mode 100644 index 0000000000..b11b9cff2b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java @@ -0,0 +1,168 @@ +/* + * + * 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.v0_8.handler; + + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.*; +import org.apache.qpid.framing.amqp_0_91.MethodDispatcher_0_91; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; + + +public class ServerMethodDispatcherImpl_0_91 + extends ServerMethodDispatcherImpl + implements MethodDispatcher_0_91 + +{ + + private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler = + BasicRecoverSyncMethodHandler.getInstance(); + private static final QueueUnbindHandler _queueUnbindHandler = + QueueUnbindHandler.getInstance(); + + + public ServerMethodDispatcherImpl_0_91(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 dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + 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/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java new file mode 100644 index 0000000000..f05219712f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java @@ -0,0 +1,95 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.BasicRecoverOkBody; +import org.apache.qpid.framing.ChannelAlertBody; +import org.apache.qpid.framing.TestContentBody; +import org.apache.qpid.framing.TestContentOkBody; +import org.apache.qpid.framing.TestIntegerBody; +import org.apache.qpid.framing.TestIntegerOkBody; +import org.apache.qpid.framing.TestStringBody; +import org.apache.qpid.framing.TestStringOkBody; +import org.apache.qpid.framing.TestTableBody; +import org.apache.qpid.framing.TestTableOkBody; +import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; + +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/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java new file mode 100644 index 0000000000..db158d05cf --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java @@ -0,0 +1,85 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.TxCommitBody; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class TxCommitHandler implements StateAwareMethodListener +{ + private static final Logger _log = Logger.getLogger(TxCommitHandler.class); + + private static TxCommitHandler _instance = new TxCommitHandler(); + + public static TxCommitHandler getInstance() + { + return _instance; + } + + private TxCommitHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, TxCommitBody body, final int channelId) throws AMQException + { + final AMQProtocolSession session = stateManager.getProtocolSession(); + + try + { + if (_log.isDebugEnabled()) + { + _log.debug("Commit received on channel " + channelId); + } + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + channel.commit(new Runnable() + { + + @Override + public void run() + { + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + } + }, true); + + + + } + catch (AMQException e) + { + throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage()); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java new file mode 100644 index 0000000000..030b8fd94f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java @@ -0,0 +1,85 @@ +/* + * + * 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.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.TxRollbackBody; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class TxRollbackHandler implements StateAwareMethodListener +{ + private static TxRollbackHandler _instance = new TxRollbackHandler(); + + public static TxRollbackHandler getInstance() + { + return _instance; + } + + private TxRollbackHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, TxRollbackBody body, final int channelId) throws AMQException + { + final AMQProtocolSession session = stateManager.getProtocolSession(); + + try + { + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + + + final MethodRegistry methodRegistry = session.getMethodRegistry(); + final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody(); + + Runnable task = new Runnable() + { + + public void run() + { + session.writeFrame(responseBody.generateFrame(channelId)); + } + }; + + channel.rollback(task); + + //Now resend all the unacknowledged messages back to the original subscribers. + //(Must be done after the TxnRollback-ok response). + // Why, are we not allowed to send messages back to client before the ok method? + channel.resend(false); + + } + catch (AMQException e) + { + throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage()); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.java new file mode 100644 index 0000000000..7152368d8d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.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.protocol.v0_8.handler; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.TxSelectBody; +import org.apache.qpid.framing.TxSelectOkBody; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; + +public class TxSelectHandler implements StateAwareMethodListener +{ + private static TxSelectHandler _instance = new TxSelectHandler(); + + public static TxSelectHandler getInstance() + { + return _instance; + } + + private TxSelectHandler() + { + } + + public void methodReceived(AMQStateManager stateManager, TxSelectBody body, int channelId) throws AMQException + { + AMQProtocolSession session = stateManager.getProtocolSession(); + + AMQChannel channel = session.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + channel.setLocalTransactional(); + + MethodRegistry methodRegistry = session.getMethodRegistry(); + TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.java new file mode 100644 index 0000000000..32a9f768ec --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.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.server.protocol.v0_8.handler; + + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; + +public class UnexpectedMethodException extends AMQException +{ + + private static final long serialVersionUID = -255921574946294892L; + + public UnexpectedMethodException(AMQMethodBody body) + { + super("Unexpected method recevied: " + body.getClass().getName()); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/HeaderPropertiesConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/HeaderPropertiesConverter.java new file mode 100755 index 0000000000..113a9c974a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/HeaderPropertiesConverter.java @@ -0,0 +1,149 @@ +/* +* +* 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.v0_8.output; + +import org.apache.qpid.AMQPInvalidClassException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; + +import java.util.HashMap; +import java.util.Map; + +public class HeaderPropertiesConverter +{ + private HeaderPropertiesConverter() + { + } + + public static BasicContentHeaderProperties convert(MessageTransferMessage messageTransferMessage, VirtualHost vhost) + { + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + + Header header = messageTransferMessage.getHeader(); + DeliveryProperties deliveryProps = header.getDeliveryProperties(); + MessageProperties messageProps = header.getMessageProperties(); + + if(deliveryProps != null) + { + if(deliveryProps.hasDeliveryMode()) + { + props.setDeliveryMode((byte)(deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT)); + } + if(deliveryProps.hasExpiration()) + { + props.setExpiration(deliveryProps.getExpiration()); + } + if(deliveryProps.hasPriority()) + { + props.setPriority((byte)deliveryProps.getPriority().getValue()); + } + if(deliveryProps.hasTimestamp()) + { + props.setTimestamp(deliveryProps.getTimestamp()); + } + } + if(messageProps != null) + { + if(messageProps.hasAppId()) + { + props.setAppId(new AMQShortString(messageProps.getAppId())); + } + if(messageProps.hasContentType()) + { + props.setContentType(messageProps.getContentType()); + } + if(messageProps.hasCorrelationId()) + { + props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId())); + } + if(messageProps.hasContentEncoding()) + { + props.setEncoding(messageProps.getContentEncoding()); + } + if(messageProps.hasMessageId()) + { + props.setMessageId("ID:" + messageProps.getMessageId().toString()); + } + if(messageProps.hasReplyTo()) + { + ReplyTo replyTo = messageProps.getReplyTo(); + String exchangeName = replyTo.getExchange(); + String routingKey = replyTo.getRoutingKey(); + if(exchangeName == null) + { + exchangeName = ""; + } + + Exchange exchange = vhost.getExchange(exchangeName); + String exchangeClass = exchange == null ? ExchangeDefaults.DIRECT_EXCHANGE_CLASS.asString() : exchange.getType().getName().asString(); + props.setReplyTo(exchangeClass + "://"+exchangeName+"//?routingkey='"+(routingKey==null ? "" : routingKey+"'")); + + } + if(messageProps.hasUserId()) + { + props.setUserId(new AMQShortString(messageProps.getUserId())); + } + + if(messageProps.hasApplicationHeaders()) + { + Map appHeaders = new HashMap(messageProps.getApplicationHeaders()); + if(messageProps.getApplicationHeaders().containsKey("x-jms-type")) + { + props.setType(String.valueOf(appHeaders.remove("x-jms-type"))); + } + + FieldTable ft = new FieldTable(); + for(Map.Entry entry : appHeaders.entrySet()) + { + try + { + ft.put(new AMQShortString(entry.getKey()), entry.getValue()); + } + catch(AMQPInvalidClassException e) + { + // TODO + // log here, but ignore - just can;t convert + } + } + props.setHeaders(ft); + + } + } + + + + + + + + return props; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java new file mode 100644 index 0000000000..bcedbd6e5f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java @@ -0,0 +1,60 @@ +/* + * + * 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.protocol.v0_8.output; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQDataBlock; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.QueueEntry; + +public interface ProtocolOutputConverter +{ + void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag); + + interface Factory + { + ProtocolOutputConverter newInstance(AMQProtocolSession session); + } + + void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) + throws AMQException; + + void writeGetOk(QueueEntry message, int channelId, long deliveryTag, int queueSize) throws AMQException; + + byte getProtocolMinorVersion(); + + byte getProtocolMajorVersion(); + + void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource msgContent, int channelId, int replyCode, AMQShortString replyText) + throws AMQException; + + void writeFrame(AMQDataBlock block); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java new file mode 100644 index 0000000000..9e7d04e0fb --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java @@ -0,0 +1,452 @@ +/* + * + * 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.v0_8.output; + +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.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicCancelOkBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.BasicGetOkBody; +import org.apache.qpid.framing.BasicReturnBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.transport.DeliveryProperties; + +import java.io.DataOutput; +import java.io.IOException; +import java.nio.ByteBuffer; + +class ProtocolOutputConverterImpl implements ProtocolOutputConverter +{ + private static final int BASIC_CLASS_ID = 60; + + private final MethodRegistry _methodRegistry; + private final AMQProtocolSession _protocolSession; + + ProtocolOutputConverterImpl(AMQProtocolSession session, MethodRegistry methodRegistry) + { + _protocolSession = session; + _methodRegistry = methodRegistry; + } + + + public AMQProtocolSession getProtocolSession() + { + return _protocolSession; + } + + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) + throws AMQException + { + AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag); + writeMessageDelivery(entry, channelId, deliverBody); + } + + + private ContentHeaderBody getContentHeaderBody(QueueEntry entry) + throws AMQException + { + if(entry.getMessage() instanceof AMQMessage) + { + return ((AMQMessage)entry.getMessage()).getContentHeaderBody(); + } + else + { + final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); + BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message, entry.getQueue().getVirtualHost()); + ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID); + chb.setBodySize(message.getSize()); + return chb; + } + } + + + private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody) + throws AMQException + { + writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody); + } + + private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody) + throws AMQException + { + + + int bodySize = (int) message.getSize(); + + if(bodySize == 0) + { + SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody, + contentHeaderBody); + + writeFrame(compositeBlock); + } + else + { + int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead(); + + + int capacity = bodySize > maxBodySize ? maxBodySize : bodySize; + + int writtenSize = capacity; + + AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity); + + CompositeAMQBodyBlock + compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody); + writeFrame(compositeBlock); + + while(writtenSize < bodySize) + { + capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize; + MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity); + writtenSize += capacity; + + writeFrame(new AMQFrame(channelId, body)); + } + } + } + + private class MessageContentSourceBody implements AMQBody + { + public static final byte TYPE = 3; + private int _length; + private MessageContentSource _message; + private int _offset; + + public MessageContentSourceBody(MessageContentSource message, int offset, int length) + { + _message = message; + _offset = offset; + _length = length; + } + + public byte getFrameType() + { + return TYPE; + } + + public int getSize() + { + return _length; + } + + public void writePayload(DataOutput buffer) throws IOException + { + ByteBuffer buf = _message.getContent(_offset, _length); + + if(buf.hasArray()) + { + buffer.write(buf.array(), buf.arrayOffset()+buf.position(), buf.remaining()); + } + else + { + + byte[] data = new byte[_length]; + + buf.get(data); + + buffer.write(data); + } + } + + public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException + { + throw new UnsupportedOperationException(); + } + } + + public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException + { + AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); + writeMessageDelivery(entry, channelId, deliver); + } + + + private AMQBody createEncodedDeliverBody(QueueEntry entry, + final long deliveryTag, + final AMQShortString consumerTag) + throws AMQException + { + + final AMQShortString exchangeName; + final AMQShortString routingKey; + + if(entry.getMessage() instanceof AMQMessage) + { + final AMQMessage message = (AMQMessage) entry.getMessage(); + final MessagePublishInfo pb = message.getMessagePublishInfo(); + exchangeName = pb.getExchange(); + routingKey = pb.getRoutingKey(); + } + else + { + MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); + DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); + exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); + routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); + } + + final boolean isRedelivered = entry.isRedelivered(); + + final AMQBody returnBlock = new EncodedDeliveryBody(deliveryTag, routingKey, exchangeName, consumerTag, isRedelivered); + return returnBlock; + } + + private class EncodedDeliveryBody implements AMQBody + { + private final long _deliveryTag; + private final AMQShortString _routingKey; + private final AMQShortString _exchangeName; + private final AMQShortString _consumerTag; + private final boolean _isRedelivered; + private AMQBody _underlyingBody; + + private EncodedDeliveryBody(long deliveryTag, AMQShortString routingKey, AMQShortString exchangeName, AMQShortString consumerTag, boolean isRedelivered) + { + _deliveryTag = deliveryTag; + _routingKey = routingKey; + _exchangeName = exchangeName; + _consumerTag = consumerTag; + _isRedelivered = isRedelivered; + } + + public AMQBody createAMQBody() + { + return _methodRegistry.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(DataOutput buffer) throws IOException + { + 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!"); + } + + @Override + public String toString() + { + return "[" + getClass().getSimpleName() + " underlyingBody: " + String.valueOf(_underlyingBody) + "]"; + } + } + + private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) + throws AMQException + { + final AMQShortString exchangeName; + final AMQShortString routingKey; + + if(entry.getMessage() instanceof AMQMessage) + { + final AMQMessage message = (AMQMessage) entry.getMessage(); + final MessagePublishInfo pb = message.getMessagePublishInfo(); + exchangeName = pb.getExchange(); + routingKey = pb.getRoutingKey(); + } + else + { + MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); + DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); + exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); + routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); + } + + final boolean isRedelivered = entry.isRedelivered(); + + BasicGetOkBody getOkBody = + _methodRegistry.createBasicGetOkBody(deliveryTag, + isRedelivered, + exchangeName, + routingKey, + queueSize); + + return getOkBody; + } + + public byte getProtocolMinorVersion() + { + return _protocolSession.getProtocolMinorVersion(); + } + + public byte getProtocolMajorVersion() + { + return getProtocolSession().getProtocolMajorVersion(); + } + + private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, + int replyCode, + AMQShortString replyText) throws AMQException + { + + BasicReturnBody basicReturnBody = + _methodRegistry.createBasicReturnBody(replyCode, + replyText, + messagePublishInfo.getExchange(), + messagePublishInfo.getRoutingKey()); + + + return basicReturnBody; + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText) + throws AMQException + { + + AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText); + + writeMessageDelivery(message, header, channelId, returnFrame); + } + + + public void writeFrame(AMQDataBlock block) + { + getProtocolSession().writeFrame(block); + } + + + public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) + { + + BasicCancelOkBody basicCancelOkBody = _methodRegistry.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(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[").append(getClass().getSimpleName()) + .append(" methodBody=").append(_methodBody) + .append(", headerBody=").append(_headerBody) + .append(", contentBody=").append(_contentBody) + .append(", channel=").append(_channel).append("]"); + return builder.toString(); + } + + } + + 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(DataOutput buffer) throws IOException + { + AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append(getClass().getSimpleName()) + .append("methodBody=").append(_methodBody) + .append(", headerBody=").append(_headerBody) + .append(", channel=").append(_channel).append("]"); + return builder.toString(); + } + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java new file mode 100644 index 0000000000..f38652fb32 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java @@ -0,0 +1,90 @@ +/* + * + * 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.protocol.v0_8.output; + +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter.Factory; +import org.apache.qpid.server.protocol.AMQProtocolSession; + +import java.util.HashMap; +import java.util.Map; + +public class ProtocolOutputConverterRegistry +{ + + private static final Map _registry = + new HashMap(); + + + static + { + register(ProtocolVersion.v8_0); + register(ProtocolVersion.v0_9); + register(ProtocolVersion.v0_91); + } + + private ProtocolOutputConverterRegistry() + { + } + + private static void register(ProtocolVersion version) + { + + _registry.put(version,new ConverterFactory(version)); + } + + + public static ProtocolOutputConverter getConverter(AMQProtocolSession session) + { + return _registry.get(session.getProtocolVersion()).newInstance(session); + } + + private static class ConverterFactory implements Factory + { + private ProtocolVersion _protocolVersion; + private MethodRegistry _methodRegistry; + private int _classId; + + public ConverterFactory(ProtocolVersion pv) + { + _protocolVersion = pv; + + } + + public synchronized ProtocolOutputConverter newInstance(AMQProtocolSession session) + { + if(_methodRegistry == null) + { + + _methodRegistry = MethodRegistry.getMethodRegistry(_protocolVersion); + + } + return new ProtocolOutputConverterImpl(session, _methodRegistry); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.java new file mode 100644 index 0000000000..ee97d5fa87 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.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.server.protocol.v0_8.state; + +/** + * States used in the AMQ protocol. Used by the finite state machine to determine + * valid responses. + */ +public enum AMQState +{ + CONNECTION_NOT_STARTED, + CONNECTION_NOT_AUTH, + CONNECTION_NOT_TUNED, + CONNECTION_NOT_OPENED, + CONNECTION_OPEN, + CONNECTION_CLOSING, + CONNECTION_CLOSED +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java new file mode 100644 index 0000000000..773a114002 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java @@ -0,0 +1,162 @@ +/* + * + * 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.v0_8.state; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.ChannelCloseBody; +import org.apache.qpid.framing.ChannelCloseOkBody; +import org.apache.qpid.framing.ChannelOpenBody; +import org.apache.qpid.framing.MethodDispatcher; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.protocol.AMQMethodEvent; +import org.apache.qpid.protocol.AMQMethodListener; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * The state manager is responsible for managing the state of the protocol session.

For each AMQProtocolHandler + * there is a separate state manager. + */ +public class AMQStateManager implements AMQMethodListener +{ + private static final Logger _logger = Logger.getLogger(AMQStateManager.class); + + private final Broker _broker; + private final AMQProtocolSession _protocolSession; + /** The current state */ + private AMQState _currentState; + + private CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet(); + + public AMQStateManager(Broker broker, AMQProtocolSession protocolSession) + { + _broker = broker; + _protocolSession = protocolSession; + _currentState = AMQState.CONNECTION_NOT_STARTED; + + } + + /** + * Get the Broker instance + * + * @return the Broker + */ + public Broker getBroker() + { + return _broker; + } + + public AMQState getCurrentState() + { + return _currentState; + } + + public void changeState(AMQState newState) throws AMQException + { + _logger.debug("State changing to " + newState + " from old state " + _currentState); + final AMQState oldState = _currentState; + _currentState = newState; + + for (StateListener l : _stateListeners) + { + l.stateChanged(oldState, newState); + } + } + + public void error(Exception e) + { + _logger.error("State manager received error notification[Current State:" + _currentState + "]: " + e, e); + for (StateListener l : _stateListeners) + { + l.error(e); + } + } + + public boolean methodReceived(AMQMethodEvent evt) throws AMQException + { + MethodDispatcher dispatcher = _protocolSession.getMethodDispatcher(); + + final int channelId = evt.getChannelId(); + B body = evt.getMethod(); + + if(channelId != 0 && _protocolSession.getChannel(channelId)== null) + { + + if(! ((body instanceof ChannelOpenBody) + || (body instanceof ChannelCloseOkBody) + || (body instanceof ChannelCloseBody))) + { + throw body.getConnectionException(AMQConstant.CHANNEL_ERROR, "channel is closed won't process:" + body); + } + + } + + return body.execute(dispatcher, channelId); + + } + + private void checkChannel(AMQMethodEvent evt, AMQProtocolSession protocolSession) + throws AMQException + { + if ((evt.getChannelId() != 0) && !(evt.getMethod() instanceof ChannelOpenBody) + && (protocolSession.getChannel(evt.getChannelId()) == null) + && !protocolSession.channelAwaitingClosure(evt.getChannelId())) + { + throw evt.getMethod().getChannelNotFoundException(evt.getChannelId()); + } + } + + public void addStateListener(StateListener listener) + { + _logger.debug("Adding state listener"); + _stateListeners.add(listener); + } + + public void removeStateListener(StateListener listener) + { + _stateListeners.remove(listener); + } + + public VirtualHostRegistry getVirtualHostRegistry() + { + return _broker.getVirtualHostRegistry(); + } + + public AMQProtocolSession getProtocolSession() + { + SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject()); + return _protocolSession; + } + + + public SubjectCreator getSubjectCreator() + { + return _broker.getSubjectCreator(getProtocolSession().getLocalAddress()); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.java new file mode 100644 index 0000000000..f61553f8a2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.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.protocol.v0_8.state; + +import org.apache.qpid.AMQException; + +/** + * @todo Not an AMQP exception as no status code. + * + * @todo Not used! Delete. + */ +public class IllegalStateTransitionException extends AMQException +{ + private AMQState _originalState; + + private Class _frame; + + public IllegalStateTransitionException(AMQState originalState, Class frame) + { + super("No valid state transition defined for receiving frame " + frame + " from state " + originalState); + _originalState = originalState; + _frame = frame; + } + + public AMQState getOriginalState() + { + return _originalState; + } + + public Class getFrameClass() + { + return _frame; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.java new file mode 100644 index 0000000000..63ab23919d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.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.protocol.v0_8.state; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQMethodBody; + +/** + * A frame listener that is informed of the protocol state when invoked and has + * the opportunity to update state. + * + */ +public interface StateAwareMethodListener +{ + void methodReceived(AMQStateManager stateManager, B evt, int channelId) throws AMQException; +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.java new file mode 100644 index 0000000000..e065ae0d42 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.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.protocol.v0_8.state; + +import org.apache.qpid.AMQException; + +public interface StateListener +{ + void stateChanged(AMQState oldState, AMQState newState) throws AMQException; + + void error(Throwable t); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java new file mode 100755 index 0000000000..1bddda2f38 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java @@ -0,0 +1,427 @@ +/* + * + * 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.v1_0; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.qpid.amqp_1_0.codec.FrameWriter; +import org.apache.qpid.amqp_1_0.framing.AMQFrame; +import org.apache.qpid.amqp_1_0.framing.FrameHandler; +import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; +import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; +import org.apache.qpid.amqp_1_0.transport.Container; +import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.FrameBody; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.common.ServerPropertyNames; +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.v1_0.Connection_1_0; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHandler +{ + static final AtomicLong _connectionIdSource = new AtomicLong(0L); + private final Port _port; + private final Transport _transport; + + //private NetworkConnection _networkDriver; + private long _readBytes; + private long _writtenBytes; + private long _lastReadTime; + private long _lastWriteTime; + private final Broker _broker; + private long _createTime = System.currentTimeMillis(); + private ConnectionEndpoint _conn; + private final long _connectionId; + + private static final ByteBuffer HEADER = + ByteBuffer.wrap(new byte[] + { + (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte) 0, + (byte) 1, + (byte) 0, + (byte) 0 + }); + + private FrameWriter _frameWriter; + private FrameHandler _frameHandler; + private Object _sendLock = new Object(); + private byte _major; + private byte _minor; + private byte _revision; + private NetworkConnection _network; + private Sender _sender; + + + static enum State { + A, + M, + Q, + P, + PROTOCOL, + MAJOR, + MINOR, + REVISION, + FRAME + } + + private State _state = State.A; + + + + public ProtocolEngine_1_0_0(final NetworkConnection networkDriver, + final Broker broker, + long id, + Port port, + Transport transport) + { + _broker = broker; + _port = port; + _transport = transport; + _connectionId = id; + if(networkDriver != null) + { + setNetworkConnection(networkDriver, networkDriver.getSender()); + } + } + + + public SocketAddress getRemoteAddress() + { + return _network.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _network.getLocalAddress(); + } + + public long getReadBytes() + { + return _readBytes; + } + + public long getWrittenBytes() + { + return _writtenBytes; + } + + public void writerIdle() + { + //Todo + } + + public void readerIdle() + { + //Todo + } + + public void setNetworkConnection(final NetworkConnection network, final Sender sender) + { + _network = network; + _sender = sender; + + Container container = new Container(_broker.getId().toString()); + + VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); + + _conn = new ConnectionEndpoint(container, asSaslServerProvider(_broker.getSubjectCreator( + getLocalAddress()))); + + Map serverProperties = new LinkedHashMap(); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.PRODUCT), QpidProperties.getProductName()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.VERSION), QpidProperties.getReleaseVersion()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_BUILD), QpidProperties.getBuildVersion()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_INSTANCE_NAME), _broker.getName()); + + _conn.setProperties(serverProperties); + + _conn.setRemoteAddress(_network.getRemoteAddress()); + _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId, _port, _transport)); + _conn.setFrameOutputHandler(this); + + _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry()); + _frameHandler = new FrameHandler(_conn); + + _sender.send(HEADER.duplicate()); + _sender.flush(); + } + + private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) + { + return new SaslServerProvider() + { + @Override + public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException + { + return subjectCreator.createSaslServer(mechanism, fqdn, null); + } + + @Override + public Principal getAuthenticatedPrincipal(SaslServer server) + { + return new UsernamePrincipal(server.getAuthorizationID()); + } + }; + } + + public String getAddress() + { + return getRemoteAddress().toString(); + } + + public boolean isDurable() + { + return false; + } + + public synchronized void received(ByteBuffer msg) + { + _lastReadTime = System.currentTimeMillis(); + if(RAW_LOGGER.isLoggable(Level.FINE)) + { + ByteBuffer dup = msg.duplicate(); + byte[] data = new byte[dup.remaining()]; + dup.get(data); + Binary bin = new Binary(data); + RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString()); + } + _readBytes += msg.remaining(); + switch(_state) + { + case A: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + break; + } + case M: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.M; + break; + } + + case Q: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.Q; + break; + } + case P: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.P; + break; + } + case PROTOCOL: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.PROTOCOL; + break; + } + case MAJOR: + if(msg.hasRemaining()) + { + _major = msg.get(); + } + else + { + _state = State.MAJOR; + break; + } + case MINOR: + if(msg.hasRemaining()) + { + _minor = msg.get(); + } + else + { + _state = State.MINOR; + break; + } + case REVISION: + if(msg.hasRemaining()) + { + _revision = msg.get(); + + _state = State.FRAME; + } + else + { + _state = State.REVISION; + break; + } + case FRAME: + if(msg.hasRemaining()) + { + _frameHandler.parse(msg); + } + } + + } + + public void exception(Throwable t) + { + t.printStackTrace(); + } + + public void closed() + { + _conn.inputClosed(); + if(_conn != null && _conn.getConnectionEventListener() != null) + { + ((Connection_1_0)_conn.getConnectionEventListener()).closed(); + } + + } + + public long getCreateTime() + { + return _createTime; + } + + + public boolean canSend() + { + return true; + } + + public void send(final AMQFrame amqFrame) + { + send(amqFrame, null); + } + + private final Logger FRAME_LOGGER = Logger.getLogger("FRM"); + private final Logger RAW_LOGGER = Logger.getLogger("RAW"); + + + public void send(final AMQFrame amqFrame, ByteBuffer buf) + { + synchronized(_sendLock) + { + + _lastWriteTime = System.currentTimeMillis(); + if(FRAME_LOGGER.isLoggable(Level.FINE)) + { + FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); + } + + + _frameWriter.setValue(amqFrame); + + + + ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize()); + + int size = _frameWriter.writeToBuffer(dup); + if(size > _conn.getMaxFrameSize()) + { + throw new OversizeFrameException(amqFrame,size); + } + + dup.flip(); + _writtenBytes += dup.limit(); + + if(RAW_LOGGER.isLoggable(Level.FINE)) + { + ByteBuffer dup2 = dup.duplicate(); + byte[] data = new byte[dup2.remaining()]; + dup2.get(data); + Binary bin = new Binary(data); + RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString()); + } + + + _sender.send(dup); + _sender.flush(); + + } + } + + public void send(short channel, FrameBody body) + { + AMQFrame frame = AMQFrame.createAMQFrame(channel, body); + send(frame); + + } + + public void close() + { + //TODO + } + + public long getConnectionId() + { + return _connectionId; + } + + public long getLastReadTime() + { + return _lastReadTime; + } + + public long getLastWriteTime() + { + return _lastWriteTime; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java new file mode 100644 index 0000000000..d614f44981 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java @@ -0,0 +1,462 @@ +/* + * + * 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.v1_0; + +import java.io.PrintWriter; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.qpid.amqp_1_0.codec.FrameWriter; +import org.apache.qpid.amqp_1_0.codec.ProtocolHandler; +import org.apache.qpid.amqp_1_0.framing.AMQFrame; +import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; +import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler; +import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; +import org.apache.qpid.amqp_1_0.transport.Container; +import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.FrameBody; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.common.ServerPropertyNames; +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.v1_0.Connection_1_0; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOutputHandler +{ + private final Port _port; + private final Transport _transport; + private long _readBytes; + private long _writtenBytes; + + private long _lastReadTime; + private long _lastWriteTime; + private final Broker _broker; + private long _createTime = System.currentTimeMillis(); + private ConnectionEndpoint _conn; + private long _connectionId; + + private static final ByteBuffer HEADER = + ByteBuffer.wrap(new byte[] + { + (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte) 3, + (byte) 1, + (byte) 0, + (byte) 0 + }); + + private static final ByteBuffer PROTOCOL_HEADER = + ByteBuffer.wrap(new byte[] + { + (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte) 0, + (byte) 1, + (byte) 0, + (byte) 0 + }); + + + private FrameWriter _frameWriter; + private ProtocolHandler _frameHandler; + private ByteBuffer _buf = ByteBuffer.allocate(1024 * 1024); + private Object _sendLock = new Object(); + private byte _major; + private byte _minor; + private byte _revision; + private PrintWriter _out; + private NetworkConnection _network; + private Sender _sender; + + + static enum State { + A, + M, + Q, + P, + PROTOCOL, + MAJOR, + MINOR, + REVISION, + FRAME + } + + private State _state = State.A; + + + public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final Broker broker, + long id, Port port, Transport transport) + { + _connectionId = id; + _broker = broker; + _port = port; + _transport = transport; + if(networkDriver != null) + { + setNetworkConnection(networkDriver, networkDriver.getSender()); + } + } + + + public SocketAddress getRemoteAddress() + { + return _network.getRemoteAddress(); + } + + public SocketAddress getLocalAddress() + { + return _network.getLocalAddress(); + } + + public long getReadBytes() + { + return _readBytes; + } + + public long getWrittenBytes() + { + return _writtenBytes; + } + + public void writerIdle() + { + //Todo + } + + public void readerIdle() + { + //Todo + } + + public void setNetworkConnection(final NetworkConnection network, final Sender sender) + { + _network = network; + _sender = sender; + + Container container = new Container(_broker.getId().toString()); + + VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); + SubjectCreator subjectCreator = _broker.getSubjectCreator(getLocalAddress()); + _conn = new ConnectionEndpoint(container, asSaslServerProvider(subjectCreator)); + + Map serverProperties = new LinkedHashMap(); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.PRODUCT), QpidProperties.getProductName()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.VERSION), QpidProperties.getReleaseVersion()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_BUILD), QpidProperties.getBuildVersion()); + serverProperties.put(Symbol.valueOf(ServerPropertyNames.QPID_INSTANCE_NAME), _broker.getName()); + + _conn.setProperties(serverProperties); + + _conn.setRemoteAddress(getRemoteAddress()); + _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId, _port, _transport)); + _conn.setFrameOutputHandler(this); + _conn.setSaslFrameOutput(this); + + _conn.setOnSaslComplete(new Runnable() + { + public void run() + { + if(_conn.isAuthenticated()) + { + _sender.send(PROTOCOL_HEADER.duplicate()); + _sender.flush(); + } + else + { + _network.close(); + } + } + }); + _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry()); + _frameHandler = new SASLFrameHandler(_conn); + + _sender.send(HEADER.duplicate()); + _sender.flush(); + + _conn.initiateSASL(subjectCreator.getMechanisms().split(" ")); + + + } + + private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) + { + return new SaslServerProvider() + { + @Override + public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException + { + return subjectCreator.createSaslServer(mechanism, fqdn, _network.getPeerPrincipal()); + } + + @Override + public Principal getAuthenticatedPrincipal(SaslServer server) + { + return new UsernamePrincipal(server.getAuthorizationID()); + } + }; + } + + public String getAddress() + { + return getRemoteAddress().toString(); + } + + public boolean isDurable() + { + return false; + } + + private final Logger RAW_LOGGER = Logger.getLogger("RAW"); + + + public synchronized void received(ByteBuffer msg) + { + _lastReadTime = System.currentTimeMillis(); + if(RAW_LOGGER.isLoggable(Level.FINE)) + { + ByteBuffer dup = msg.duplicate(); + byte[] data = new byte[dup.remaining()]; + dup.get(data); + Binary bin = new Binary(data); + RAW_LOGGER.fine("RECV[" + getRemoteAddress() + "] : " + bin.toString()); + } + _readBytes += msg.remaining(); + switch(_state) + { + case A: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + break; + } + case M: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.M; + break; + } + + case Q: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.Q; + break; + } + case P: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.P; + break; + } + case PROTOCOL: + if(msg.hasRemaining()) + { + msg.get(); + } + else + { + _state = State.PROTOCOL; + break; + } + case MAJOR: + if(msg.hasRemaining()) + { + _major = msg.get(); + } + else + { + _state = State.MAJOR; + break; + } + case MINOR: + if(msg.hasRemaining()) + { + _minor = msg.get(); + } + else + { + _state = State.MINOR; + break; + } + case REVISION: + if(msg.hasRemaining()) + { + _revision = msg.get(); + + _state = State.FRAME; + } + else + { + _state = State.REVISION; + break; + } + case FRAME: + if(msg.hasRemaining()) + { + _frameHandler = _frameHandler.parse(msg); + } + } + + } + + public void exception(Throwable t) + { + t.printStackTrace(); + } + + public void closed() + { + // todo + _conn.inputClosed(); + if (_conn != null && _conn.getConnectionEventListener() != null) + { + ((Connection_1_0) _conn.getConnectionEventListener()).closed(); + } + + } + + public long getCreateTime() + { + return _createTime; + } + + + public boolean canSend() + { + return true; + } + + public void send(final AMQFrame amqFrame) + { + send(amqFrame, null); + } + + private static final Logger FRAME_LOGGER = Logger.getLogger("FRM"); + + + public void send(final AMQFrame amqFrame, ByteBuffer buf) + { + + synchronized (_sendLock) + { + _lastWriteTime = System.currentTimeMillis(); + if (FRAME_LOGGER.isLoggable(Level.FINE)) + { + FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); + } + + _frameWriter.setValue(amqFrame); + + ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize()); + + int size = _frameWriter.writeToBuffer(dup); + if (size > _conn.getMaxFrameSize()) + { + throw new OversizeFrameException(amqFrame, size); + } + + dup.flip(); + _writtenBytes += dup.limit(); + + if (RAW_LOGGER.isLoggable(Level.FINE)) + { + ByteBuffer dup2 = dup.duplicate(); + byte[] data = new byte[dup2.remaining()]; + dup2.get(data); + Binary bin = new Binary(data); + RAW_LOGGER.fine("SEND[" + getRemoteAddress() + "] : " + bin.toString()); + } + + _sender.send(dup); + _sender.flush(); + + + } + } + + public void send(short channel, FrameBody body) + { + AMQFrame frame = AMQFrame.createAMQFrame(channel, body); + send(frame); + + } + + public void close() + { + _sender.close(); + } + + public void setLogOutput(final PrintWriter out) + { + _out = out; + } + + public long getConnectionId() + { + return _connectionId; + } + + public long getLastReadTime() + { + return _lastReadTime; + } + + public long getLastWriteTime() + { + return _lastWriteTime; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java index 44ee945548..a4e9046d84 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java @@ -63,9 +63,9 @@ import org.apache.qpid.typedmessage.TypedBytesContentReader; import org.apache.qpid.typedmessage.TypedBytesFormatException; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.MessageMetaData_1_0; -import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java index 18affc7161..a7cd07a301 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java @@ -33,7 +33,7 @@ import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.store.StoredMessage; import java.nio.ByteBuffer; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.java deleted file mode 100644 index f427cc7206..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.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.qpid.server.state; - -/** - * States used in the AMQ protocol. Used by the finite state machine to determine - * valid responses. - */ -public enum AMQState -{ - CONNECTION_NOT_STARTED, - CONNECTION_NOT_AUTH, - CONNECTION_NOT_TUNED, - CONNECTION_NOT_OPENED, - CONNECTION_OPEN, - CONNECTION_CLOSING, - CONNECTION_CLOSED -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java deleted file mode 100644 index ff41536a23..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java +++ /dev/null @@ -1,162 +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.state; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.ChannelCloseBody; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ChannelOpenBody; -import org.apache.qpid.framing.MethodDispatcher; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.protocol.AMQMethodEvent; -import org.apache.qpid.protocol.AMQMethodListener; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; - -import java.util.concurrent.CopyOnWriteArraySet; - -/** - * The state manager is responsible for managing the state of the protocol session.

For each AMQProtocolHandler - * there is a separate state manager. - */ -public class AMQStateManager implements AMQMethodListener -{ - private static final Logger _logger = Logger.getLogger(AMQStateManager.class); - - private final Broker _broker; - private final AMQProtocolSession _protocolSession; - /** The current state */ - private AMQState _currentState; - - private CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet(); - - public AMQStateManager(Broker broker, AMQProtocolSession protocolSession) - { - _broker = broker; - _protocolSession = protocolSession; - _currentState = AMQState.CONNECTION_NOT_STARTED; - - } - - /** - * Get the Broker instance - * - * @return the Broker - */ - public Broker getBroker() - { - return _broker; - } - - public AMQState getCurrentState() - { - return _currentState; - } - - public void changeState(AMQState newState) throws AMQException - { - _logger.debug("State changing to " + newState + " from old state " + _currentState); - final AMQState oldState = _currentState; - _currentState = newState; - - for (StateListener l : _stateListeners) - { - l.stateChanged(oldState, newState); - } - } - - public void error(Exception e) - { - _logger.error("State manager received error notification[Current State:" + _currentState + "]: " + e, e); - for (StateListener l : _stateListeners) - { - l.error(e); - } - } - - public boolean methodReceived(AMQMethodEvent evt) throws AMQException - { - MethodDispatcher dispatcher = _protocolSession.getMethodDispatcher(); - - final int channelId = evt.getChannelId(); - B body = evt.getMethod(); - - if(channelId != 0 && _protocolSession.getChannel(channelId)== null) - { - - if(! ((body instanceof ChannelOpenBody) - || (body instanceof ChannelCloseOkBody) - || (body instanceof ChannelCloseBody))) - { - throw body.getConnectionException(AMQConstant.CHANNEL_ERROR, "channel is closed won't process:" + body); - } - - } - - return body.execute(dispatcher, channelId); - - } - - private void checkChannel(AMQMethodEvent evt, AMQProtocolSession protocolSession) - throws AMQException - { - if ((evt.getChannelId() != 0) && !(evt.getMethod() instanceof ChannelOpenBody) - && (protocolSession.getChannel(evt.getChannelId()) == null) - && !protocolSession.channelAwaitingClosure(evt.getChannelId())) - { - throw evt.getMethod().getChannelNotFoundException(evt.getChannelId()); - } - } - - public void addStateListener(StateListener listener) - { - _logger.debug("Adding state listener"); - _stateListeners.add(listener); - } - - public void removeStateListener(StateListener listener) - { - _stateListeners.remove(listener); - } - - public VirtualHostRegistry getVirtualHostRegistry() - { - return _broker.getVirtualHostRegistry(); - } - - public AMQProtocolSession getProtocolSession() - { - SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject()); - return _protocolSession; - } - - - public SubjectCreator getSubjectCreator() - { - return _broker.getSubjectCreator(getProtocolSession().getLocalAddress()); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.java deleted file mode 100644 index cec67a8a6d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.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.state; - -import org.apache.qpid.AMQException; - -/** - * @todo Not an AMQP exception as no status code. - * - * @todo Not used! Delete. - */ -public class IllegalStateTransitionException extends AMQException -{ - private AMQState _originalState; - - private Class _frame; - - public IllegalStateTransitionException(AMQState originalState, Class frame) - { - super("No valid state transition defined for receiving frame " + frame + " from state " + originalState); - _originalState = originalState; - _frame = frame; - } - - public AMQState getOriginalState() - { - return _originalState; - } - - public Class getFrameClass() - { - return _frame; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.java deleted file mode 100644 index b543728f3b..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.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.state; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQMethodBody; - -/** - * A frame listener that is informed of the protocol state when invoked and has - * the opportunity to update state. - * - */ -public interface StateAwareMethodListener -{ - void methodReceived(AMQStateManager stateManager, B evt, int channelId) throws AMQException; -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java deleted file mode 100644 index 00fc09867b..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java +++ /dev/null @@ -1,30 +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.state; - -import org.apache.qpid.AMQException; - -public interface StateListener -{ - void stateChanged(AMQState oldState, AMQState newState) throws AMQException; - - void error(Throwable t); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java index 0fab60b6f3..df17ae8318 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java @@ -20,8 +20,8 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageMetaData_0_10; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; +import org.apache.qpid.server.protocol.v0_10.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageMetaData_1_0; import java.nio.ByteBuffer; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java deleted file mode 100755 index 8f3822be6c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java +++ /dev/null @@ -1,94 +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.subscription; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; - - -class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener -{ - private static final Logger _logger = Logger.getLogger(ExplicitAcceptDispositionChangeListener.class); - - - private final QueueEntry _entry; - private final Subscription_0_10 _sub; - - public ExplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) - { - _entry = entry; - _sub = subscription_0_10; - } - - public void onAccept() - { - final Subscription_0_10 subscription = getSubscription(); - if(subscription != null && _entry.isAcquiredBy(_sub)) - { - subscription.getSessionModel().acknowledge(subscription, _entry); - } - else - { - _logger.warn("MessageAccept received for message which has not been acquired (likely client error)"); - } - - } - - public void onRelease(boolean setRedelivered) - { - final Subscription_0_10 subscription = getSubscription(); - if(subscription != null && _entry.isAcquiredBy(_sub)) - { - subscription.release(_entry, setRedelivered); - } - else - { - _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); - } - } - - public void onReject() - { - final Subscription_0_10 subscription = getSubscription(); - if(subscription != null && _entry.isAcquiredBy(_sub)) - { - subscription.reject(_entry); - } - else - { - _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); - } - - } - - public boolean acquire() - { - return _entry.acquire(getSubscription()); - } - - - private Subscription_0_10 getSubscription() - { - return _sub; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java deleted file mode 100755 index 826082cc65..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java +++ /dev/null @@ -1,89 +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.subscription; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; - -class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener -{ - private static final Logger _logger = Logger.getLogger(ImplicitAcceptDispositionChangeListener.class); - - - private final QueueEntry _entry; - private Subscription_0_10 _sub; - - public ImplicitAcceptDispositionChangeListener(QueueEntry entry, Subscription_0_10 subscription_0_10) - { - _entry = entry; - _sub = subscription_0_10; - } - - public void onAccept() - { - _logger.warn("MessageAccept received for message which is using NONE as the accept mode (likely client error)"); - } - - public void onRelease(boolean setRedelivered) - { - if(_entry.isAcquiredBy(_sub)) - { - getSubscription().release(_entry, setRedelivered); - } - else - { - _logger.warn("MessageRelease received for message which has not been acquired (likely client error)"); - } - } - - public void onReject() - { - if(_entry.isAcquiredBy(_sub)) - { - getSubscription().reject(_entry); - } - else - { - _logger.warn("MessageReject received for message which has not been acquired (likely client error)"); - } - - } - - public boolean acquire() - { - boolean acquired = _entry.acquire(getSubscription()); - if(acquired) - { - getSubscription().recordUnacknowledged(_entry); - } - return acquired; - - } - - public Subscription_0_10 getSubscription() - { - return _sub; - } - - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java deleted file mode 100755 index 8a2a370236..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java +++ /dev/null @@ -1,57 +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.subscription; - -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.transport.Method; - -public class MessageAcceptCompletionListener implements Method.CompletionListener -{ - private final Subscription_0_10 _sub; - private final QueueEntry _entry; - private final ServerSession _session; - private boolean _restoreCredit; - - public MessageAcceptCompletionListener(Subscription_0_10 sub, ServerSession session, QueueEntry entry, boolean restoreCredit) - { - super(); - _sub = sub; - _entry = entry; - _session = session; - _restoreCredit = restoreCredit; - } - - public void onComplete(Method method) - { - if(_restoreCredit) - { - _sub.restoreCredit(_entry); - } - if(_entry.isAcquiredBy(_sub)) - { - _session.acknowledge(_sub, _entry); - } - - _session.removeDispositionListener(method); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java deleted file mode 100644 index 3659243cea..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java +++ /dev/null @@ -1,85 +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.subscription; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageFlowMode; - -import java.util.Map; - -/** - * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory - * primarily assists testing although in future more sophisticated subscribers may need a different subscription - * implementation. - * - * @see org.apache.qpid.server.queue.AMQQueue - */ -public interface SubscriptionFactory -{ - Subscription createSubscription(int channel, - AMQProtocolSession protocolSession, - AMQShortString consumerTag, - boolean acks, - FieldTable filters, - boolean noLocal, FlowCreditManager creditManager) throws AMQException; - - - Subscription createSubscription(AMQChannel channel, - AMQProtocolSession protocolSession, - AMQShortString consumerTag, - boolean acks, - FieldTable filters, - boolean noLocal, - FlowCreditManager creditManager, - ClientDeliveryMethod clientMethod, - RecordDeliveryMethod recordMethod - ) - throws AMQException; - - - SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel, - AMQProtocolSession session, - AMQShortString consumerTag, - FieldTable filters, - boolean noLocal, - FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod) throws AMQException; - - Subscription_0_10 createSubscription(final ServerSession session, - final String destination, - final MessageAcceptMode acceptMode, - final MessageAcquireMode acquireMode, - final MessageFlowMode flowMode, - final FlowCreditManager_0_10 creditManager, - final FilterManager filterManager, - final Map arguments); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java deleted file mode 100644 index a2e30b6ae7..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.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.server.subscription; - -import org.apache.qpid.AMQException; -import org.apache.qpid.common.AMQPFilterTypes; -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.filter.FilterManager; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageFlowMode; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -public class SubscriptionFactoryImpl implements SubscriptionFactory -{ - private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0); - - 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, getNextSubscriptionId()); - } - else if(acks) - { - return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); - } - else - { - return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); - } - } - - public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel, - final AMQProtocolSession session, - final AMQShortString consumerTag, - final FieldTable filters, - final boolean noLocal, - final FlowCreditManager creditManager, - final ClientDeliveryMethod deliveryMethod, - final RecordDeliveryMethod recordMethod) throws AMQException - { - return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId()); - } - - public Subscription_0_10 createSubscription(final ServerSession session, - final String destination, - final MessageAcceptMode acceptMode, - final MessageAcquireMode acquireMode, - final MessageFlowMode flowMode, - final FlowCreditManager_0_10 creditManager, - final FilterManager filterManager, - final Map arguments) - { - return new Subscription_0_10(session, destination, acceptMode, acquireMode, - flowMode, creditManager, filterManager, arguments, getNextSubscriptionId()); - } - - public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl(); - - private static long getNextSubscriptionId() - { - return SUB_ID_GENERATOR.getAndIncrement(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java deleted file mode 100644 index 29a8f4e27e..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ /dev/null @@ -1,849 +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.subscription; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.filter.FilterManagerFactory; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.SubscriptionActor; -import org.apache.qpid.server.logging.messages.SubscriptionMessages; -import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.ServerTransaction; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Encapsulation of a supscription to a queue.

Ties together the protocol session of a subscriber, the consumer tag - * that was given out by the broker and the channel id.

- */ -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 = new AtomicReference(State.ACTIVE); - private volatile AMQQueue.Context _queueContext; - - private final ClientDeliveryMethod _deliveryMethod; - private final RecordDeliveryMethod _recordMethod; - - private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); - - private final Map _properties = new ConcurrentHashMap(); - - private final Lock _stateChangeLock; - - private final long _subscriptionID; - private LogSubject _logSubject; - private LogActor _logActor; - private final AtomicLong _deliveredCount = new AtomicLong(0); - private final AtomicLong _deliveredBytes = new AtomicLong(0); - - private final AtomicLong _unacknowledgedCount = new AtomicLong(0); - private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); - - private long _createTime = System.currentTimeMillis(); - - - static final class BrowserSubscription extends SubscriptionImpl - { - public BrowserSubscription(AMQChannel channel, AMQProtocolSession protocolSession, - AMQShortString consumerTag, FieldTable filters, - boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) - throws AMQException - { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); - } - - - 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 entry - * @param batch - * @throws AMQException - */ - @Override - public void send(QueueEntry entry, boolean batch) 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(entry, deliveryTag); - } - - } - - @Override - public boolean wouldSuspend(QueueEntry msg) - { - return false; - } - - } - - public static class NoAckSubscription extends SubscriptionImpl - { - private volatile AutoCommitTransaction _txn; - - public NoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, - AMQShortString consumerTag, FieldTable filters, - boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) - throws AMQException - { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); - } - - - public boolean isBrowser() - { - return false; - } - - @Override - public boolean isExplicitAcknowledge() - { - 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 - * @param batch - * @throws AMQException - */ - @Override - public void send(QueueEntry entry, boolean batch) throws AMQException - { - // 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(_txn == null) - { - _txn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); - } - _txn.dequeue(getQueue(), entry.getMessage(), NOOP); - - entry.dequeue(); - - synchronized (getChannel()) - { - getChannel().getProtocolSession().setDeferFlush(batch); - long deliveryTag = getChannel().getNextDeliveryTag(); - - sendToClient(entry, deliveryTag); - - } - entry.dispose(); - - - } - - @Override - public boolean wouldSuspend(QueueEntry msg) - { - return false; - } - - private static final ServerTransaction.Action NOOP = - new ServerTransaction.Action() - { - @Override - public void postCommit() - { - } - - @Override - public void onRollback() - { - } - }; - } - - /** - * NoAck Subscription for use with BasicGet method. - */ - 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, - long subscriptionID) - throws AMQException - { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); - } - - public boolean isTransient() - { - return true; - } - - public boolean wouldSuspend(QueueEntry msg) - { - return !getCreditManager().useCreditForMessage(msg.getMessage().getSize()); - } - - } - - static final class AckSubscription extends SubscriptionImpl - { - public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, - AMQShortString consumerTag, FieldTable filters, - boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) - throws AMQException - { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); - } - - - 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 - * @param batch - * @throws AMQException - */ - @Override - public void send(QueueEntry entry, boolean batch) throws AMQException - { - - - synchronized (getChannel()) - { - getChannel().getProtocolSession().setDeferFlush(batch); - long deliveryTag = getChannel().getNextDeliveryTag(); - - addUnacknowledgedMessage(entry); - recordMessageDelivery(entry, deliveryTag); - sendToClient(entry, deliveryTag); - - - } - } - - - - } - - - private static final Logger _logger = Logger.getLogger(SubscriptionImpl.class); - - private final AMQChannel _channel; - - private final AMQShortString _consumerTag; - - - private boolean _noLocal; - - private final FlowCreditManager _creditManager; - - private FilterManager _filters; - - private final Boolean _autoClose; - - 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, - long subscriptionID) - throws AMQException - { - _subscriptionID = subscriptionID; - _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 AMQSessionModel getSessionModel() - { - return _channel; - } - - public Long getDelivered() - { - return _deliveredCount.get(); - } - - public synchronized void setQueue(AMQQueue queue, boolean exclusive) - { - if(getQueue() != null) - { - throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); - } - _queue = queue; - - _logSubject = new SubscriptionLogSubject(this); - _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); - - if (CurrentActor.get().getRootMessageLogger(). - isMessageEnabled(CurrentActor.get(), _logSubject, SubscriptionMessages.CREATE_LOG_HIERARCHY)) - { - // Get the string value of the filters - String filterLogString = null; - if (_filters != null && _filters.hasFilters()) - { - filterLogString = _filters.toString(); - } - - if (isAutoClose()) - { - if (filterLogString == null) - { - filterLogString = ""; - } - else - { - filterLogString += ","; - } - filterLogString += "AutoClose"; - } - - if (isBrowser()) - { - // We do not need to check for null here as all Browsers are AutoClose - filterLogString +=",Browser"; - } - - CurrentActor.get(). - message(_logSubject, - SubscriptionMessages.CREATE(filterLogString, - queue.isDurable() && exclusive, - filterLogString != null)); - } - } - - 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 entry - * @param batch - * @throws AMQException - */ - abstract public void send(QueueEntry entry, boolean batch) throws AMQException; - - - public boolean isSuspended() - { - return !isActive() || _channel.isSuspended() || _deleted.get() || _channel.getConnectionModel().isStopped(); - } - - /** - * Callback indicating that a queue has been deleted. - * - * @param queue The queue to delete - */ - public void queueDeleted(AMQQueue queue) - { - _deleted.set(true); - } - - public boolean hasInterest(QueueEntry entry) - { - //check that the message hasn't been rejected - if (entry.isRejectedBy(getSubscriptionID())) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Subscription:" + this + " rejected message:" + entry); - } - } - - if (_noLocal) - { - AMQMessage message = (AMQMessage) entry.getMessage(); - - final Object publisherReference = message.getConnectionIdentifier(); - - // We don't want local messages so check to see if message is one we sent - Object localReference = getProtocolSession().getReference(); - - if(publisherReference != null && publisherReference.equals(localReference)) - { - return false; - } - } - - - if (_logger.isDebugEnabled()) - { - _logger.debug("(" + this + ") checking filters for message (" + entry); - } - return checkFilters(entry); - - } - - private boolean checkFilters(QueueEntry msg) - { - return (_filters == null) || _filters.allAllow(msg); - } - - 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(); - } - //Log Subscription closed - CurrentActor.get().message(_logSubject, SubscriptionMessages.CLOSE()); - } - - public boolean isClosed() - { - return getState() == State.CLOSED; - } - - - public boolean wouldSuspend(QueueEntry msg) - { - return !_creditManager.useCreditForMessage(msg.getMessage().getSize()); - } - - public boolean trySendLock() - { - return _stateChangeLock.tryLock(); - } - - public void getSendLock() - { - _stateChangeLock.lock(); - } - - public void releaseSendLock() - { - _stateChangeLock.unlock(); - } - - public AMQChannel getChannel() - { - return _channel; - } - - public AMQShortString getConsumerTag() - { - return _consumerTag; - } - - public String getConsumerName() - { - return _consumerTag == null ? null : _consumerTag.asString(); - } - - public long getSubscriptionID() - { - return _subscriptionID; - } - - public AMQProtocolSession getProtocolSession() - { - return _channel.getProtocolSession(); - } - - public LogActor getLogActor() - { - return _logActor; - } - - public AMQQueue getQueue() - { - return _queue; - } - - public void onDequeue(final QueueEntry queueEntry) - { - restoreCredit(queueEntry); - } - - public void releaseQueueEntry(final QueueEntry queueEntry) - { - restoreCredit(queueEntry); - } - - public void restoreCredit(final QueueEntry queueEntry) - { - _creditManager.restoreCredit(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); - } - } - CurrentActor.get().message(_logSubject,SubscriptionMessages.STATE(_state.get().toString())); - } - - public State getState() - { - return _state.get(); - } - - - public void setStateListener(final StateListener listener) - { - _stateListener = listener; - } - - - public AMQQueue.Context getQueueContext() - { - return _queueContext; - } - - public void setQueueContext(AMQQueue.Context context) - { - _queueContext = context; - } - - - protected void sendToClient(final QueueEntry entry, final long deliveryTag) - throws AMQException - { - _deliveryMethod.deliverToClient(this,entry,deliveryTag); - _deliveredCount.incrementAndGet(); - _deliveredBytes.addAndGet(entry.getSize()); - } - - - 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; - } - - public void confirmAutoClose() - { - ProtocolOutputConverter converter = getChannel().getProtocolSession().getProtocolOutputConverter(); - converter.confirmConsumerAutoClose(getChannel().getChannelId(), getConsumerTag()); - } - - public boolean acquires() - { - return !isBrowser(); - } - - public boolean seesRequeues() - { - return !isBrowser(); - } - - public boolean isTransient() - { - return false; - } - - public void set(String key, Object value) - { - _properties.put(key, value); - } - - public Object get(String key) - { - return _properties.get(key); - } - - - public void setNoLocal(boolean noLocal) - { - _noLocal = noLocal; - } - - abstract boolean isBrowser(); - - public String getCreditMode() - { - return "WINDOW"; - } - - public boolean isBrowsing() - { - return isBrowser(); - } - - public boolean isExplicitAcknowledge() - { - return true; - } - - public boolean isDurable() - { - return false; - } - - public boolean isExclusive() - { - return getQueue().hasExclusiveSubscriber(); - } - - public String getName() - { - return String.valueOf(_consumerTag); - } - - public Map getArguments() - { - return null; - } - - public boolean isSessionTransactional() - { - return _channel.isTransactional(); - } - - public long getCreateTime() - { - return _createTime; - } - - public void queueEmpty() throws AMQException - { - if (isAutoClose()) - { - _queue.unregisterSubscription(this); - - confirmAutoClose(); - } - } - - public void flushBatched() - { - _channel.getProtocolSession().setDeferFlush(false); - - _channel.getProtocolSession().flushBatched(); - } - - public long getBytesOut() - { - return _deliveredBytes.longValue(); - } - - public long getMessagesOut() - { - return _deliveredCount.longValue(); - } - - - protected void addUnacknowledgedMessage(QueueEntry entry) - { - final long size = entry.getSize(); - _unacknowledgedBytes.addAndGet(size); - _unacknowledgedCount.incrementAndGet(); - entry.addStateChangeListener(new QueueEntry.StateChangeListener() - { - public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState) - { - if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED)) - { - _unacknowledgedBytes.addAndGet(-size); - _unacknowledgedCount.decrementAndGet(); - entry.removeStateChangeListener(this); - } - } - }); - } - - public long getUnacknowledgedBytes() - { - return _unacknowledgedBytes.longValue(); - } - - public long getUnacknowledgedMessages() - { - return _unacknowledgedCount.longValue(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java deleted file mode 100644 index 2f237f0f3a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ /dev/null @@ -1,1077 +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.subscription; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.flow.CreditCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.flow.WindowCreditManager; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.logging.messages.ChannelMessages; -import org.apache.qpid.server.logging.messages.SubscriptionMessages; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.InboundMessageAdapter; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.ServerTransaction; -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.MessageDeliveryPriority; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Method; -import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.ReplyTo; -import org.apache.qpid.transport.Struct; -import org.apache.qpid.url.AMQBindingURL; - -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.QUEUE_FORMAT; -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT; - -import java.net.URISyntaxException; -import java.nio.ByteBuffer; -import java.text.MessageFormat; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, LogSubject -{ - private final long _subscriptionID; - - private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this); - - private static final Option[] BATCHED = new Option[] { Option.BATCH }; - - private final Lock _stateChangeLock = new ReentrantLock(); - - private final AtomicReference _state = new AtomicReference(State.ACTIVE); - private volatile AMQQueue.Context _queueContext; - private final AtomicBoolean _deleted = new AtomicBoolean(false); - - - private FlowCreditManager_0_10 _creditManager; - - private StateListener _stateListener = new StateListener() - { - - public void stateChange(Subscription sub, State oldState, State newState) - { - CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString())); - } - }; - private AMQQueue _queue; - private final String _destination; - private boolean _noLocal; - private final FilterManager _filters; - private final MessageAcceptMode _acceptMode; - private final MessageAcquireMode _acquireMode; - private MessageFlowMode _flowMode; - private final ServerSession _session; - private final AtomicBoolean _stopped = new AtomicBoolean(true); - private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0]; - - private LogActor _logActor; - private final Map _properties = new ConcurrentHashMap(); - private String _traceExclude; - private String _trace; - private final long _createTime = System.currentTimeMillis(); - private final AtomicLong _deliveredCount = new AtomicLong(0); - private final AtomicLong _deliveredBytes = new AtomicLong(0); - private final AtomicLong _unacknowledgedCount = new AtomicLong(0); - private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); - - private final Map _arguments; - private int _deferredMessageCredit; - private long _deferredSizeCredit; - - - public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode, - MessageAcquireMode acquireMode, - MessageFlowMode flowMode, - FlowCreditManager_0_10 creditManager, - FilterManager filters,Map arguments, long subscriptionId) - { - _subscriptionID = subscriptionId; - _session = session; - _postIdSettingAction = new AddMessageDispositionListenerAction(session); - _destination = destination; - _acceptMode = acceptMode; - _acquireMode = acquireMode; - _creditManager = creditManager; - _flowMode = flowMode; - _filters = filters; - _creditManager.addStateListener(this); - _arguments = arguments == null ? Collections. emptyMap() : - Collections. unmodifiableMap(arguments); - _state.set(_creditManager.hasCredit() ? State.ACTIVE : State.SUSPENDED); - - } - - public void setNoLocal(boolean noLocal) - { - _noLocal = noLocal; - } - - public AMQQueue getQueue() - { - return _queue; - } - - public QueueEntry.SubscriptionAcquiredState getOwningState() - { - return _owningState; - } - - public void setQueue(AMQQueue queue, boolean exclusive) - { - if(getQueue() != null) - { - throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); - } - _queue = queue; - - Map arguments = queue.getArguments(); - _traceExclude = (String) arguments.get("qpid.trace.exclude"); - _trace = (String) arguments.get("qpid.trace.id"); - String filterLogString = null; - - _logActor = GenericActor.getInstance(this); - if (CurrentActor.get().getRootMessageLogger().isMessageEnabled(_logActor, this, SubscriptionMessages.CREATE_LOG_HIERARCHY)) - { - filterLogString = getFilterLogString(); - CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive, - filterLogString.length() > 0)); - } - } - - public String getConsumerName() - { - return _destination; - } - - public boolean isSuspended() - { - return !isActive() || _deleted.get() || _session.isClosing() || _session.getConnectionModel().isStopped(); // TODO check for Session suspension - } - - public boolean hasInterest(QueueEntry entry) - { - - - - //check that the message hasn't been rejected - if (entry.isRejectedBy(getSubscriptionID())) - { - - return false; - } - - if (_noLocal && entry.getMessage() instanceof MessageTransferMessage) - { - Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference(); - if (connectionRef != null && connectionRef == _session.getReference()) - { - return false; - } - } - - - return checkFilters(entry); - - - } - - private boolean checkFilters(QueueEntry entry) - { - return (_filters == null) || _filters.allAllow(entry); - } - - public boolean isClosed() - { - return getState() == State.CLOSED; - } - - public boolean isBrowser() - { - return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; - } - - public boolean seesRequeues() - { - return _acquireMode != MessageAcquireMode.NOT_ACQUIRED || _acceptMode == MessageAcceptMode.EXPLICIT; - } - - 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); - CurrentActor.get().message(getLogSubject(), SubscriptionMessages.CLOSE()); - } - finally - { - _stateChangeLock.unlock(); - } - - - - } - - public Long getDelivered() - { - return _deliveredCount.get(); - } - - 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 static class AddMessageDispositionListenerAction implements Runnable - { - private MessageTransfer _xfr; - private ServerSession.MessageDispositionChangeListener _action; - private ServerSession _session; - - public AddMessageDispositionListenerAction(ServerSession session) - { - _session = session; - } - - public void setXfr(MessageTransfer xfr) - { - _xfr = xfr; - } - - public void setAction(ServerSession.MessageDispositionChangeListener action) - { - _action = action; - } - - public void run() - { - if(_action != null) - { - _session.onMessageDispositionChange(_xfr, _action); - } - } - } - - private final AddMessageDispositionListenerAction _postIdSettingAction; - - public void send(final QueueEntry entry, boolean batch) throws AMQException - { - ServerMessage serverMsg = entry.getMessage(); - - - MessageTransfer xfr; - - DeliveryProperties deliveryProps; - MessageProperties messageProps = null; - - if(serverMsg instanceof MessageTransferMessage) - { - - MessageTransferMessage msg = (MessageTransferMessage) serverMsg; - DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties(); - messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties(); - - deliveryProps = new DeliveryProperties(); - if(origDeliveryProps != null) - { - if(origDeliveryProps.hasDeliveryMode()) - { - deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); - } - if(origDeliveryProps.hasExchange()) - { - deliveryProps.setExchange(origDeliveryProps.getExchange()); - } - if(origDeliveryProps.hasExpiration()) - { - deliveryProps.setExpiration(origDeliveryProps.getExpiration()); - } - if(origDeliveryProps.hasPriority()) - { - deliveryProps.setPriority(origDeliveryProps.getPriority()); - } - if(origDeliveryProps.hasRoutingKey()) - { - deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); - } - if(origDeliveryProps.hasTimestamp()) - { - deliveryProps.setTimestamp(origDeliveryProps.getTimestamp()); - } - if(origDeliveryProps.hasTtl()) - { - deliveryProps.setTtl(origDeliveryProps.getTtl()); - } - - - } - - deliveryProps.setRedelivered(entry.isRedelivered()); - - if(_trace != null && messageProps == null) - { - messageProps = new MessageProperties(); - } - - Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties()); - - - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); - } - else if(serverMsg instanceof AMQMessage) - { - AMQMessage message_0_8 = (AMQMessage) serverMsg; - deliveryProps = new DeliveryProperties(); - messageProps = new MessageProperties(); - - int size = (int) message_0_8.getSize(); - ByteBuffer body = ByteBuffer.allocate(size); - message_0_8.getContent(body, 0); - body.flip(); - - BasicContentHeaderProperties properties = - (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties(); - final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); - if(exchange != null) - { - deliveryProps.setExchange(exchange.toString()); - } - deliveryProps.setExpiration(message_0_8.getExpiration()); - deliveryProps.setImmediate(message_0_8.isImmediate()); - deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority())); - deliveryProps.setRedelivered(entry.isRedelivered()); - deliveryProps.setRoutingKey(message_0_8.getRoutingKey()); - deliveryProps.setTimestamp(properties.getTimestamp()); - - messageProps.setContentEncoding(properties.getEncodingAsString()); - messageProps.setContentLength(size); - if(properties.getAppId() != null) - { - messageProps.setAppId(properties.getAppId().getBytes()); - } - messageProps.setContentType(properties.getContentTypeAsString()); - if(properties.getCorrelationId() != null) - { - messageProps.setCorrelationId(properties.getCorrelationId().getBytes()); - } - - if(properties.getReplyTo() != null && properties.getReplyTo().length() != 0) - { - String origReplyToString = properties.getReplyTo().asString(); - ReplyTo replyTo = new ReplyTo(); - // if the string looks like a binding URL, then attempt to parse it... - try - { - AMQBindingURL burl = new AMQBindingURL(origReplyToString); - AMQShortString routingKey = burl.getRoutingKey(); - if(routingKey != null) - { - replyTo.setRoutingKey(routingKey.asString()); - } - - AMQShortString exchangeName = burl.getExchangeName(); - if(exchangeName != null) - { - replyTo.setExchange(exchangeName.asString()); - } - } - catch (URISyntaxException e) - { - replyTo.setRoutingKey(origReplyToString); - } - messageProps.setReplyTo(replyTo); - - } - - if(properties.getMessageId() != null) - { - try - { - String messageIdAsString = properties.getMessageIdAsString(); - if(messageIdAsString.startsWith("ID:")) - { - messageIdAsString = messageIdAsString.substring(3); - } - UUID uuid = UUID.fromString(messageIdAsString); - messageProps.setMessageId(uuid); - } - catch(IllegalArgumentException e) - { - // ignore - can't parse - } - } - - - - if(properties.getUserId() != null) - { - messageProps.setUserId(properties.getUserId().getBytes()); - } - - FieldTable fieldTable = properties.getHeaders(); - - Map appHeaders = FieldTable.convertToMap(fieldTable); - - if(properties.getType() != null) - { - appHeaders.put("x-jms-type", properties.getTypeAsString()); - } - - - messageProps.setApplicationHeaders(appHeaders); - - Header header = new Header(deliveryProps, messageProps, null); - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); - } - else - { - - deliveryProps = new DeliveryProperties(); - messageProps = new MessageProperties(); - - int size = (int) serverMsg.getSize(); - ByteBuffer body = ByteBuffer.allocate(size); - serverMsg.getContent(body, 0); - body.flip(); - - - deliveryProps.setExpiration(serverMsg.getExpiration()); - deliveryProps.setImmediate(serverMsg.isImmediate()); - deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); - deliveryProps.setRedelivered(entry.isRedelivered()); - deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); - deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); - - messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); - messageProps.setContentLength(size); - messageProps.setContentType(serverMsg.getMessageHeader().getMimeType()); - if(serverMsg.getMessageHeader().getCorrelationId() != null) - { - messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); - } - - // TODO - ReplyTo - - Header header = new Header(deliveryProps, messageProps, null); - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); - } - - boolean excludeDueToFederation = false; - - if(_trace != null) - { - if(!messageProps.hasApplicationHeaders()) - { - messageProps.setApplicationHeaders(new HashMap()); - } - Map appHeaders = messageProps.getApplicationHeaders(); - String trace = (String) appHeaders.get("x-qpid.trace"); - if(trace == null) - { - trace = _trace; - } - else - { - if(_traceExclude != null) - { - excludeDueToFederation = Arrays.asList(trace.split(",")).contains(_traceExclude); - } - trace+=","+_trace; - } - appHeaders.put("x-qpid.trace",trace); - } - - if(!excludeDueToFederation) - { - if(_acceptMode == MessageAcceptMode.NONE && _acquireMode != MessageAcquireMode.PRE_ACQUIRED) - { - xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW)); - } - else if(_flowMode == MessageFlowMode.WINDOW) - { - xfr.setCompletionListener(new Method.CompletionListener() - { - public void onComplete(Method method) - { - deferredAddCredit(1, entry.getSize()); - } - }); - } - - - _postIdSettingAction.setXfr(xfr); - if(_acceptMode == MessageAcceptMode.EXPLICIT) - { - _postIdSettingAction.setAction(new ExplicitAcceptDispositionChangeListener(entry, this)); - } - else if(_acquireMode != MessageAcquireMode.PRE_ACQUIRED) - { - _postIdSettingAction.setAction(new ImplicitAcceptDispositionChangeListener(entry, this)); - } - else - { - _postIdSettingAction.setAction(null); - } - - - _session.sendMessage(xfr, _postIdSettingAction); - entry.incrementDeliveryCount(); - _deliveredCount.incrementAndGet(); - _deliveredBytes.addAndGet(entry.getSize()); - if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED) - { - forceDequeue(entry, false); - } - else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED) - { - recordUnacknowledged(entry); - } - } - else - { - forceDequeue(entry, _flowMode == MessageFlowMode.WINDOW); - - } - } - - void recordUnacknowledged(QueueEntry entry) - { - _unacknowledgedCount.incrementAndGet(); - _unacknowledgedBytes.addAndGet(entry.getSize()); - } - - private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit) - { - _deferredMessageCredit += deferredMessageCredit; - _deferredSizeCredit += deferredSizeCredit; - - } - - public void flushCreditState(boolean strict) - { - if(strict || !isSuspended() || _deferredMessageCredit >= 200 - || !(_creditManager instanceof WindowCreditManager) - || ((WindowCreditManager)_creditManager).getMessageCreditLimit() < 400 ) - { - _creditManager.restoreCredit(_deferredMessageCredit, _deferredSizeCredit); - _deferredMessageCredit = 0; - _deferredSizeCredit = 0l; - } - } - - private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) - { - AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); - dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(), - new ServerTransaction.Action() - { - public void postCommit() - { - if (restoreCredit) - { - restoreCredit(entry); - } - entry.discard(); - } - - public void onRollback() - { - - } - }); - } - - void reject(final QueueEntry entry) - { - entry.setRedelivered(); - entry.routeToAlternate(); - if(entry.isAcquiredBy(this)) - { - entry.discard(); - } - } - - void release(final QueueEntry entry, final boolean setRedelivered) - { - if (setRedelivered) - { - entry.setRedelivered(); - } - - if (getSessionModel().isClosing() || !setRedelivered) - { - entry.decrementDeliveryCount(); - } - - if (isMaxDeliveryLimitReached(entry)) - { - sendToDLQOrDiscard(entry); - } - else - { - entry.release(); - } - } - - protected void sendToDLQOrDiscard(QueueEntry entry) - { - final Exchange alternateExchange = entry.getQueue().getAlternateExchange(); - final LogActor logActor = CurrentActor.get(); - final ServerMessage msg = entry.getMessage(); - if (alternateExchange != null) - { - final InboundMessage m = new InboundMessageAdapter(entry); - - final List destinationQueues = alternateExchange.route(m); - - if (destinationQueues == null || destinationQueues.isEmpty()) - { - entry.discard(); - - logActor.message( ChannelMessages.DISCARDMSG_NOROUTE(msg.getMessageNumber(), alternateExchange.getName())); - } - else - { - entry.routeToAlternate(); - - //output operational logging for each delivery post commit - for (final BaseQueue destinationQueue : destinationQueues) - { - logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); - } - } - } - else - { - entry.discard(); - logActor.message(ChannelMessages.DISCARDMSG_NOALTEXCH(msg.getMessageNumber(), entry.getQueue().getName(), msg.getRoutingKey())); - } - } - - private boolean isMaxDeliveryLimitReached(QueueEntry entry) - { - final int maxDeliveryLimit = entry.getQueue().getMaximumDeliveryCount(); - return (maxDeliveryLimit > 0 && entry.getDeliveryCount() >= maxDeliveryLimit); - } - - public void queueDeleted(AMQQueue queue) - { - _deleted.set(true); - } - - public boolean wouldSuspend(QueueEntry entry) - { - return !_creditManager.useCreditForMessage(entry.getMessage().getSize()); - } - - public boolean trySendLock() - { - return _stateChangeLock.tryLock(); - } - - - public void getSendLock() - { - _stateChangeLock.lock(); - } - - public void releaseSendLock() - { - _stateChangeLock.unlock(); - } - - public void restoreCredit(QueueEntry queueEntry) - { - _creditManager.restoreCredit(1, queueEntry.getSize()); - } - - public void onDequeue(QueueEntry queueEntry) - { - // no-op for 0-10, credit restored by completing command. - } - - public void releaseQueueEntry(QueueEntry queueEntry) - { - // no-op for 0-10, credit restored by completing command. - } - - public void setStateListener(StateListener listener) - { - _stateListener = listener; - } - - public State getState() - { - return _state.get(); - } - - public AMQQueue.Context getQueueContext() - { - return _queueContext; - } - - public void setQueueContext(AMQQueue.Context queueContext) - { - _queueContext = queueContext; - } - - public boolean isActive() - { - return getState() == State.ACTIVE; - } - - public void set(String key, Object value) - { - _properties.put(key, value); - } - - public Object get(String key) - { - return _properties.get(key); - } - - - public FlowCreditManager_0_10 getCreditManager() - { - return _creditManager; - } - - - public void stop() - { - try - { - getSendLock(); - - if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED)) - { - _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED); - } - _stopped.set(true); - FlowCreditManager_0_10 creditManager = getCreditManager(); - creditManager.clearCredit(); - } - finally - { - releaseSendLock(); - } - } - - public void addCredit(MessageCreditUnit unit, long value) - { - FlowCreditManager_0_10 creditManager = getCreditManager(); - - switch (unit) - { - case MESSAGE: - - creditManager.addCredit(value, 0L); - break; - case BYTE: - creditManager.addCredit(0l, value); - break; - } - - _stopped.set(false); - - if(creditManager.hasCredit()) - { - if(_state.compareAndSet(State.SUSPENDED, State.ACTIVE)) - { - _stateListener.stateChange(this, State.SUSPENDED, State.ACTIVE); - } - } - - } - - public void setFlowMode(MessageFlowMode flowMode) - { - - - _creditManager.removeListener(this); - - switch(flowMode) - { - case CREDIT: - _creditManager = new CreditCreditManager(0l,0l); - break; - case WINDOW: - _creditManager = new WindowCreditManager(0l,0l); - break; - default: - throw new RuntimeException("Unknown message flow mode: " + flowMode); - } - _flowMode = flowMode; - if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED)) - { - _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED); - } - - _creditManager.addStateListener(this); - - } - - public boolean isStopped() - { - return _stopped.get(); - } - - public boolean acquires() - { - return _acquireMode == MessageAcquireMode.PRE_ACQUIRED; - } - - public void acknowledge(QueueEntry entry) - { - // TODO Fix Store Context / cleanup - if(entry.isAcquiredBy(this)) - { - _unacknowledgedBytes.addAndGet(-entry.getSize()); - _unacknowledgedCount.decrementAndGet(); - entry.discard(); - } - } - - public void flush() throws AMQException - { - flushCreditState(true); - _queue.flushSubscription(this); - stop(); - } - - public long getSubscriptionID() - { - return _subscriptionID; - } - - public LogActor getLogActor() - { - return _logActor; - } - - public boolean isTransient() - { - return false; - } - - public ServerSession getSessionModel() - { - return _session; - } - - public boolean isBrowsing() - { - return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; - } - - public boolean isExclusive() - { - return getQueue().hasExclusiveSubscriber(); - } - - public boolean isDurable() - { - return false; - } - - - public boolean isExplicitAcknowledge() - { - return _acceptMode == MessageAcceptMode.EXPLICIT; - } - - public String getCreditMode() - { - return _flowMode.toString(); - } - - public String getName() - { - return _destination; - } - - public Map getArguments() - { - return _arguments; - } - - public boolean isSessionTransactional() - { - return _session.isTransactional(); - } - - public void queueEmpty() - { - } - - public long getCreateTime() - { - return _createTime; - } - - public String toLogString() - { - String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(), - _queue.getNameShortString()); - String result = "[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getSubscriptionID()) + "(" - // queueString is "vh(/{0})/qu({1}) " so need to trim - + queueInfo.substring(0, queueInfo.length() - 1) + ")" + "] "; - return result; - } - - private String getFilterLogString() - { - StringBuilder filterLogString = new StringBuilder(); - String delimiter = ", "; - boolean hasEntries = false; - if (_filters != null && _filters.hasFilters()) - { - filterLogString.append(_filters.toString()); - hasEntries = true; - } - - if (isBrowser()) - { - if (hasEntries) - { - filterLogString.append(delimiter); - } - filterLogString.append("Browser"); - hasEntries = true; - } - - if (isDurable()) - { - if (hasEntries) - { - filterLogString.append(delimiter); - } - filterLogString.append("Durable"); - hasEntries = true; - } - - return filterLogString.toString(); - } - - public LogSubject getLogSubject() - { - return (LogSubject) this; - } - - - public void flushBatched() - { - _session.getConnection().flush(); - } - - public long getBytesOut() - { - return _deliveredBytes.longValue(); - } - - public long getMessagesOut() - { - return _deliveredCount.longValue(); - } - - public long getUnacknowledgedBytes() - { - return _unacknowledgedBytes.longValue(); - } - - public long getUnacknowledgedMessages() - { - return _unacknowledgedCount.longValue(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java deleted file mode 100644 index 3a2cb7556d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ /dev/null @@ -1,551 +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.transport; - -import java.net.SocketAddress; -import java.security.Principal; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; -import javax.security.auth.Subject; -import org.apache.qpid.AMQException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.security.AuthorizationHolder; -import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; -import org.apache.qpid.server.stats.StatisticsCounter; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionCloseCode; -import org.apache.qpid.transport.ExecutionErrorCode; -import org.apache.qpid.transport.ExecutionException; -import org.apache.qpid.transport.Method; -import org.apache.qpid.transport.ProtocolEvent; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.network.NetworkConnection; - -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT; -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT; -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT; - -public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder -{ - private Runnable _onOpenTask; - private AtomicBoolean _logClosed = new AtomicBoolean(false); - private LogActor _actor = GenericActor.getInstance(this); - - private Subject _authorizedSubject = null; - private Principal _authorizedPrincipal = null; - private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; - private final long _connectionId; - private final Object _reference = new Object(); - private VirtualHost _virtualHost; - private Port _port; - private AtomicLong _lastIoTime = new AtomicLong(); - private boolean _blocking; - private Principal _peerPrincipal; - private NetworkConnection _networkConnection; - private Transport _transport; - private volatile boolean _stopped; - - public ServerConnection(final long connectionId) - { - _connectionId = connectionId; - } - - public Object getReference() - { - return _reference; - } - - @Override - protected void invoke(Method method) - { - super.invoke(method); - } - - @Override - protected void setState(State state) - { - super.setState(state); - - if (state == State.OPEN) - { - if (_onOpenTask != null) - { - _onOpenTask.run(); - } - _actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", getClientVersion(), true, true, true)); - - getVirtualHost().getConnectionRegistry().registerConnection(this); - } - - if (state == State.CLOSE_RCVD || state == State.CLOSED || state == State.CLOSING) - { - if(_virtualHost != null) - { - _virtualHost.getConnectionRegistry().deregisterConnection(this); - } - } - - if (state == State.CLOSED) - { - logClosed(); - } - } - - protected void logClosed() - { - if(_logClosed.compareAndSet(false, true)) - { - CurrentActor.get().message(this, ConnectionMessages.CLOSE()); - } - } - - @Override - public ServerConnectionDelegate getConnectionDelegate() - { - return (ServerConnectionDelegate) super.getConnectionDelegate(); - } - - public void setConnectionDelegate(ServerConnectionDelegate delegate) - { - super.setConnectionDelegate(delegate); - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public void setVirtualHost(VirtualHost virtualHost) - { - _virtualHost = virtualHost; - - initialiseStatistics(); - } - - @Override - public Port getPort() - { - return _port; - } - - public void setPort(Port port) - { - _port = port; - } - - @Override - public Transport getTransport() - { - return _transport; - } - - @Override - public void stop() - { - _stopped = true; - } - - @Override - public boolean isStopped() - { - return _stopped; - } - - public void setTransport(Transport transport) - { - _transport = transport; - } - - public void onOpen(final Runnable task) - { - _onOpenTask = task; - } - - public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException - { - ExecutionException ex = new ExecutionException(); - ExecutionErrorCode code = ExecutionErrorCode.INTERNAL_ERROR; - try - { - code = ExecutionErrorCode.get(cause.getCode()); - } - catch (IllegalArgumentException iae) - { - // Ignore, already set to INTERNAL_ERROR - } - ex.setErrorCode(code); - ex.setDescription(message); - ((ServerSession)session).invoke(ex); - - ((ServerSession)session).close(cause, message); - } - - public LogSubject getLogSubject() - { - return (LogSubject) this; - } - - @Override - public void received(ProtocolEvent event) - { - _lastIoTime.set(System.currentTimeMillis()); - if (event.isConnectionControl()) - { - CurrentActor.set(_actor); - } - else - { - ServerSession channel = (ServerSession) getSession(event.getChannel()); - LogActor channelActor = null; - - if (channel != null) - { - channelActor = channel.getLogActor(); - } - - CurrentActor.set(channelActor == null ? _actor : channelActor); - } - - try - { - super.received(event); - } - finally - { - CurrentActor.remove(); - } - } - - public String toLogString() - { - boolean hasVirtualHost = (null != this.getVirtualHost()); - boolean hasClientId = (null != getClientId()); - - if (hasClientId && hasVirtualHost) - { - return "[" + - MessageFormat.format(CONNECTION_FORMAT, - getConnectionId(), - getClientId(), - getRemoteAddressString(), - getVirtualHost().getName()) - + "] "; - } - else if (hasClientId) - { - return "[" + - MessageFormat.format(USER_FORMAT, - getConnectionId(), - getClientId(), - getRemoteAddressString()) - + "] "; - - } - else - { - return "[" + - MessageFormat.format(SOCKET_FORMAT, - getConnectionId(), - getRemoteAddressString()) - + "] "; - } - } - - public LogActor getLogActor() - { - return _actor; - } - - public void close(AMQConstant cause, String message) throws AMQException - { - closeSubscriptions(); - ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL; - try - { - replyCode = ConnectionCloseCode.get(cause.getCode()); - } - catch (IllegalArgumentException iae) - { - // Ignore - } - close(replyCode, message); - } - - public synchronized void block() - { - if(!_blocking) - { - _blocking = true; - for(AMQSessionModel ssn : getSessionModels()) - { - ssn.block(); - } - } - } - - public synchronized void unblock() - { - if(_blocking) - { - _blocking = false; - for(AMQSessionModel ssn : getSessionModels()) - { - ssn.unblock(); - } - } - } - - @Override - public synchronized void registerSession(final Session ssn) - { - super.registerSession(ssn); - if(_blocking) - { - ((ServerSession)ssn).block(); - } - } - - @Override - public synchronized void removeSession(final Session ssn) - { - super.removeSession(ssn); - } - - public List getSessionModels() - { - List sessions = new ArrayList(); - for (Session ssn : getChannels()) - { - sessions.add((AMQSessionModel) ssn); - } - return sessions; - } - - public void registerMessageDelivered(long messageSize) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - _virtualHost.registerMessageDelivered(messageSize); - } - - public void registerMessageReceived(long messageSize, long timestamp) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - _virtualHost.registerMessageReceived(messageSize, timestamp); - } - - public StatisticsCounter getMessageReceiptStatistics() - { - return _messagesReceived; - } - - public StatisticsCounter getDataReceiptStatistics() - { - return _dataReceived; - } - - public StatisticsCounter getMessageDeliveryStatistics() - { - return _messagesDelivered; - } - - public StatisticsCounter getDataDeliveryStatistics() - { - return _dataDelivered; - } - - public void resetStatistics() - { - _messagesDelivered.reset(); - _dataDelivered.reset(); - _messagesReceived.reset(); - _dataReceived.reset(); - } - - public void initialiseStatistics() - { - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId()); - _dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId()); - _messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId()); - _dataReceived = new StatisticsCounter("data-received-" + getConnectionId()); - } - - /** - * @return authorizedSubject - */ - public Subject getAuthorizedSubject() - { - return _authorizedSubject; - } - - /** - * Sets the authorized subject. It also extracts the UsernamePrincipal from the subject - * and caches it for optimisation purposes. - * - * @param authorizedSubject - */ - public void setAuthorizedSubject(final Subject authorizedSubject) - { - if (authorizedSubject == null) - { - _authorizedSubject = null; - _authorizedPrincipal = null; - } - else - { - _authorizedSubject = authorizedSubject; - _authorizedPrincipal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(authorizedSubject); - } - } - - public Principal getAuthorizedPrincipal() - { - return _authorizedPrincipal; - } - - public long getConnectionId() - { - return _connectionId; - } - - public boolean isSessionNameUnique(byte[] name) - { - return !super.hasSessionWithName(name); - } - - public String getRemoteAddressString() - { - return String.valueOf(getRemoteAddress()); - } - - public String getUserName() - { - return _authorizedPrincipal.getName(); - } - - @Override - public void closed() - { - closeSubscriptions(); - super.closed(); - } - - private void closeSubscriptions() - { - for (Session ssn : getChannels()) - { - ((ServerSession)ssn).unregisterSubscriptions(); - } - } - - public void receivedComplete() - { - for (Session ssn : getChannels()) - { - ((ServerSession)ssn).receivedComplete(); - } - } - - @Override - public void send(ProtocolEvent event) - { - _lastIoTime.set(System.currentTimeMillis()); - super.send(event); - } - - public long getLastIoTime() - { - return _lastIoTime.longValue(); - } - - - public String getClientId() - { - return getConnectionDelegate().getClientId(); - } - - public String getClientVersion() - { - return getConnectionDelegate().getClientVersion(); - } - - public String getPrincipalAsString() - { - return getAuthorizedPrincipal().getName(); - } - - public long getSessionCountLimit() - { - return getChannelMax(); - } - - public Principal getPeerPrincipal() - { - return _peerPrincipal; - } - - public void setPeerPrincipal(Principal peerPrincipal) - { - _peerPrincipal = peerPrincipal; - } - - @Override - public void setRemoteAddress(SocketAddress remoteAddress) - { - super.setRemoteAddress(remoteAddress); - } - - @Override - public void setLocalAddress(SocketAddress localAddress) - { - super.setLocalAddress(localAddress); - } - - public void setNetworkConnection(NetworkConnection network) - { - _networkConnection = network; - } - - public NetworkConnection getNetworkConnection() - { - return _networkConnection; - } - - public void doHeartbeat() - { - super.doHeartBeat(); - - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java deleted file mode 100644 index 4170f36771..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ /dev/null @@ -1,351 +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.transport; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.properties.ConnectionStartProperties; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SubjectCreator; -import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; -import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.virtualhost.State; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.*; -import org.apache.qpid.transport.network.NetworkConnection; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD; - -public class ServerConnectionDelegate extends ServerDelegate -{ - private static final Logger LOGGER = LoggerFactory.getLogger(ServerConnectionDelegate.class); - - private final Broker _broker; - private final String _localFQDN; - private int _maxNoOfChannels; - private Map _clientProperties; - private final SubjectCreator _subjectCreator; - - public ServerConnectionDelegate(Broker broker, String localFQDN, SubjectCreator subjectCreator) - { - this(createConnectionProperties(broker), Collections.singletonList((Object)"en_US"), broker, localFQDN, subjectCreator); - } - - private ServerConnectionDelegate(Map properties, - List locales, - Broker broker, - String localFQDN, - SubjectCreator subjectCreator) - { - super(properties, parseToList(subjectCreator.getMechanisms()), locales); - - _broker = broker; - _localFQDN = localFQDN; - _maxNoOfChannels = (Integer)broker.getAttribute(Broker.CONNECTION_SESSION_COUNT_LIMIT); - _subjectCreator = subjectCreator; - } - - private static List getFeatures(Broker broker) - { - String brokerDisabledFeatures = System.getProperty(BrokerProperties.PROPERTY_DISABLED_FEATURES); - final List features = new ArrayList(); - if (brokerDisabledFeatures == null || !brokerDisabledFeatures.contains(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR)) - { - features.add(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR); - } - - return Collections.unmodifiableList(features); - } - - private static Map createConnectionProperties(final Broker broker) - { - final Map map = new HashMap(); - // Federation tag is used by the client to identify the broker instance - map.put(ServerPropertyNames.FEDERATION_TAG, broker.getId().toString()); - final List features = getFeatures(broker); - if (features != null && features.size() > 0) - { - map.put(ServerPropertyNames.QPID_FEATURES, features); - } - - map.put(ServerPropertyNames.PRODUCT, QpidProperties.getProductName()); - map.put(ServerPropertyNames.VERSION, QpidProperties.getReleaseVersion()); - map.put(ServerPropertyNames.QPID_BUILD, QpidProperties.getBuildVersion()); - map.put(ServerPropertyNames.QPID_INSTANCE_NAME, broker.getName()); - - return map; - } - - private static List parseToList(String mechanisms) - { - List list = new ArrayList(); - StringTokenizer tokenizer = new StringTokenizer(mechanisms, " "); - while(tokenizer.hasMoreTokens()) - { - list.add(tokenizer.nextToken()); - } - return list; - } - - public ServerSession getSession(Connection conn, SessionAttach atc) - { - SessionDelegate serverSessionDelegate = new ServerSessionDelegate(); - - ServerSession ssn = new ServerSession(conn, serverSessionDelegate, new Binary(atc.getName()), 0); - - return ssn; - } - - protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException - { - return _subjectCreator.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal()); - - } - - protected void secure(final SaslServer ss, final Connection conn, final byte[] response) - { - final ServerConnection sconn = (ServerConnection) conn; - final SubjectAuthenticationResult authResult = _subjectCreator.authenticate(ss, response); - - if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus())) - { - tuneAuthorizedConnection(sconn); - sconn.setAuthorizedSubject(authResult.getSubject()); - } - else if (AuthenticationStatus.CONTINUE.equals(authResult.getStatus())) - { - connectionAuthContinue(sconn, authResult.getChallenge()); - } - else - { - connectionAuthFailed(sconn, authResult.getCause()); - } - } - - @Override - public void connectionClose(Connection conn, ConnectionClose close) - { - final ServerConnection sconn = (ServerConnection) conn; - try - { - sconn.logClosed(); - } - finally - { - sconn.closeCode(close); - sconn.setState(CLOSE_RCVD); - sendConnectionCloseOkAndCloseSender(conn); - } - } - - public void connectionOpen(Connection conn, ConnectionOpen open) - { - final ServerConnection sconn = (ServerConnection) conn; - - VirtualHost vhost; - String vhostName; - if(open.hasVirtualHost()) - { - vhostName = open.getVirtualHost(); - } - else - { - vhostName = ""; - } - vhost = _broker.getVirtualHostRegistry().getVirtualHost(vhostName); - - SecurityManager.setThreadSubject(sconn.getAuthorizedSubject()); - - if(vhost != null) - { - sconn.setVirtualHost(vhost); - - if (!vhost.getSecurityManager().accessVirtualhost(vhostName, sconn.getRemoteAddress())) - { - sconn.setState(Connection.State.CLOSING); - sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Permission denied '"+vhostName+"'")); - } - else if (vhost.getState() != State.ACTIVE) - { - sconn.setState(Connection.State.CLOSING); - sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Virtual host '"+vhostName+"' is not active")); - } - else - { - sconn.setState(Connection.State.OPEN); - sconn.invoke(new ConnectionOpenOk(Collections.emptyList())); - } - } - else - { - sconn.setState(Connection.State.CLOSING); - sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'")); - } - - } - - @Override - public void connectionTuneOk(final Connection conn, final ConnectionTuneOk ok) - { - ServerConnection sconn = (ServerConnection) conn; - int okChannelMax = ok.getChannelMax(); - - if (okChannelMax > getChannelMax()) - { - LOGGER.error("Connection '" + sconn.getConnectionId() + "' being severed, " + - "client connectionTuneOk returned a channelMax (" + okChannelMax + - ") above the server's offered limit (" + getChannelMax() +")"); - - //Due to the error we must forcefully close the connection without negotiation - sconn.getSender().close(); - return; - } - - final NetworkConnection networkConnection = sconn.getNetworkConnection(); - - if(ok.hasHeartbeat()) - { - int heartbeat = ok.getHeartbeat(); - if(heartbeat < 0) - { - heartbeat = 0; - } - - networkConnection.setMaxReadIdle(2 * heartbeat); - networkConnection.setMaxWriteIdle(heartbeat); - - } - else - { - networkConnection.setMaxReadIdle(0); - networkConnection.setMaxWriteIdle(0); - } - - setConnectionTuneOkChannelMax(sconn, okChannelMax); - } - - @Override - public int getChannelMax() - { - return _maxNoOfChannels; - } - - protected void setChannelMax(int channelMax) - { - _maxNoOfChannels = channelMax; - } - - @Override public void sessionDetach(Connection conn, SessionDetach dtc) - { - // To ensure a clean detach, we stop any remaining subscriptions. Stop ensures - // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the stop - // completes. - stopAllSubscriptions(conn, dtc); - Session ssn = conn.getSession(dtc.getChannel()); - ((ServerSession)ssn).setClose(true); - super.sessionDetach(conn, dtc); - } - - private void stopAllSubscriptions(Connection conn, SessionDetach dtc) - { - final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel()); - final Collection subs = ssn.getSubscriptions(); - for (Subscription_0_10 subscription_0_10 : subs) - { - subscription_0_10.stop(); - } - } - - - @Override - public void sessionAttach(final Connection conn, final SessionAttach atc) - { - final Session ssn; - - if(isSessionNameUnique(atc.getName(), conn)) - { - super.sessionAttach(conn, atc); - } - else - { - ssn = getSession(conn, atc); - ssn.invoke(new SessionDetached(atc.getName(), SessionDetachCode.SESSION_BUSY)); - ssn.closed(); - } - } - - private boolean isSessionNameUnique(final byte[] name, final Connection conn) - { - final ServerConnection sconn = (ServerConnection) conn; - final String userId = sconn.getUserName(); - - final Iterator connections = - ((ServerConnection)conn).getVirtualHost().getConnectionRegistry().getConnections().iterator(); - while(connections.hasNext()) - { - final AMQConnectionModel amqConnectionModel = (AMQConnectionModel) connections.next(); - if (userId.equals(amqConnectionModel.getUserName()) && !amqConnectionModel.isSessionNameUnique(name)) - { - return false; - } - } - return true; - } - - @Override - public void connectionStartOk(Connection conn, ConnectionStartOk ok) - { - _clientProperties = ok.getClientProperties(); - super.connectionStartOk(conn, ok); - } - - public Map getClientProperties() - { - return _clientProperties; - } - - public String getClientId() - { - return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.CLIENT_ID_0_10); - } - - public String getClientVersion() - { - return _clientProperties == null ? null : (String) _clientProperties.get(ConnectionStartProperties.VERSION_0_10); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java deleted file mode 100644 index 3449cc5237..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ /dev/null @@ -1,1003 +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.transport; - -import java.security.Principal; -import java.text.MessageFormat; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -import javax.security.auth.Subject; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQStoreException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.TransactionTimeoutHelper; -import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.LogMessage; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.logging.messages.ChannelMessages; -import org.apache.qpid.server.logging.subjects.ChannelLogSubject; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.security.AuthorizationHolder; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.txn.AlreadyKnownDtxException; -import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; -import org.apache.qpid.server.txn.DistributedTransaction; -import org.apache.qpid.server.txn.DtxNotSelectedException; -import org.apache.qpid.server.txn.IncorrectDtxStateException; -import org.apache.qpid.server.txn.JoinAndResumeDtxException; -import org.apache.qpid.server.txn.LocalTransaction; -import org.apache.qpid.server.txn.NotAssociatedDtxException; -import org.apache.qpid.server.txn.RollbackOnlyDtxException; -import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.txn.SuspendAndFailDtxException; -import org.apache.qpid.server.txn.TimeoutDtxException; -import org.apache.qpid.server.txn.UnknownDtxBranchException; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; -import static org.apache.qpid.util.Serial.gt; - -public class ServerSession extends Session - implements AuthorizationHolder, - AMQSessionModel, LogSubject, AsyncAutoCommitTransaction.FutureRecorder -{ - private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class); - - private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); - private static final int PRODUCER_CREDIT_TOPUP_THRESHOLD = 1 << 30; - private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500; - - private final UUID _id = UUID.randomUUID(); - private long _createTime = System.currentTimeMillis(); - private LogActor _actor = GenericActor.getInstance(this); - - private final Set _blockingEntities = Collections.synchronizedSet(new HashSet()); - - private final AtomicBoolean _blocking = new AtomicBoolean(false); - private ChannelLogSubject _logSubject; - private final AtomicInteger _outstandingCredit = new AtomicInteger(UNLIMITED_CREDIT); - - public static interface MessageDispositionChangeListener - { - public void onAccept(); - - public void onRelease(boolean setRedelivered); - - public void onReject(); - - public boolean acquire(); - - - } - - public static interface Task - { - public void doTask(ServerSession session); - } - - - private final SortedMap _messageDispositionListenerMap = - new ConcurrentSkipListMap(); - - private ServerTransaction _transaction; - - private final AtomicLong _txnStarts = new AtomicLong(0); - private final AtomicLong _txnCommits = new AtomicLong(0); - private final AtomicLong _txnRejects = new AtomicLong(0); - private final AtomicLong _txnCount = new AtomicLong(0); - - private Map _subscriptions = new ConcurrentHashMap(); - - private final List _taskList = new CopyOnWriteArrayList(); - - private final TransactionTimeoutHelper _transactionTimeoutHelper; - - private AtomicReference _forcedCloseLogMessage = new AtomicReference(); - - public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) - { - super(connection, delegate, name, expiry); - _transaction = new AsyncAutoCommitTransaction(this.getMessageStore(),this); - _logSubject = new ChannelLogSubject(this); - - _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() - { - @Override - public void doTimeoutAction(String reason) throws AMQException - { - getConnectionModel().closeSession(ServerSession.this, AMQConstant.RESOURCE_ERROR, reason); - } - }); - } - - protected void setState(State state) - { - super.setState(state); - - if (state == State.OPEN) - { - _actor.message(ChannelMessages.CREATE()); - if(_blocking.get()) - { - invokeBlock(); - } - } - } - - private void invokeBlock() - { - invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT)); - invoke(new MessageStop("")); - } - - @Override - protected boolean isFull(int id) - { - return isCommandsFull(id); - } - - public void enqueue(final ServerMessage message, final List queues) - { - if(_outstandingCredit.get() != UNLIMITED_CREDIT - && _outstandingCredit.decrementAndGet() == (Integer.MAX_VALUE - PRODUCER_CREDIT_TOPUP_THRESHOLD)) - { - _outstandingCredit.addAndGet(PRODUCER_CREDIT_TOPUP_THRESHOLD); - invoke(new MessageFlow("",MessageCreditUnit.MESSAGE, PRODUCER_CREDIT_TOPUP_THRESHOLD)); - } - getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime()); - PostEnqueueAction postTransactionAction = new PostEnqueueAction(queues, message, isTransactional()) ; - _transaction.enqueue(queues,message, postTransactionAction); - incrementOutstandingTxnsIfNecessary(); - } - - - public void sendMessage(MessageTransfer xfr, - Runnable postIdSettingAction) - { - getConnectionModel().registerMessageDelivered(xfr.getBodySize()); - invoke(xfr, postIdSettingAction); - } - - public void onMessageDispositionChange(MessageTransfer xfr, MessageDispositionChangeListener acceptListener) - { - _messageDispositionListenerMap.put(xfr.getId(), acceptListener); - } - - - private static interface MessageDispositionAction - { - void performAction(MessageDispositionChangeListener listener); - } - - public void accept(RangeSet ranges) - { - dispositionChange(ranges, new MessageDispositionAction() - { - public void performAction(MessageDispositionChangeListener listener) - { - listener.onAccept(); - } - }); - } - - - public void release(RangeSet ranges, final boolean setRedelivered) - { - dispositionChange(ranges, new MessageDispositionAction() - { - public void performAction(MessageDispositionChangeListener listener) - { - listener.onRelease(setRedelivered); - } - }); - } - - public void reject(RangeSet ranges) - { - dispositionChange(ranges, new MessageDispositionAction() - { - public void performAction(MessageDispositionChangeListener listener) - { - listener.onReject(); - } - }); - } - - public RangeSet acquire(RangeSet transfers) - { - RangeSet acquired = RangeSetFactory.createRangeSet(); - - if(!_messageDispositionListenerMap.isEmpty()) - { - Iterator unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); - Iterator rangeIter = transfers.iterator(); - - if(rangeIter.hasNext()) - { - Range range = rangeIter.next(); - - while(range != null && unacceptedMessages.hasNext()) - { - int next = unacceptedMessages.next(); - while(gt(next, range.getUpper())) - { - if(rangeIter.hasNext()) - { - range = rangeIter.next(); - } - else - { - range = null; - break; - } - } - if(range != null && range.includes(next)) - { - MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.get(next); - if(changeListener != null && changeListener.acquire()) - { - acquired.add(next); - } - } - - - } - - } - - - } - - return acquired; - } - - public void dispositionChange(RangeSet ranges, MessageDispositionAction action) - { - if(ranges != null) - { - - if(ranges.size() == 1) - { - Range r = ranges.getFirst(); - for(int i = r.getLower(); i <= r.getUpper(); i++) - { - MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(i); - if(changeListener != null) - { - action.performAction(changeListener); - } - } - } - else if(!_messageDispositionListenerMap.isEmpty()) - { - Iterator unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); - Iterator rangeIter = ranges.iterator(); - - if(rangeIter.hasNext()) - { - Range range = rangeIter.next(); - - while(range != null && unacceptedMessages.hasNext()) - { - int next = unacceptedMessages.next(); - while(gt(next, range.getUpper())) - { - if(rangeIter.hasNext()) - { - range = rangeIter.next(); - } - else - { - range = null; - break; - } - } - if(range != null && range.includes(next)) - { - MessageDispositionChangeListener changeListener = _messageDispositionListenerMap.remove(next); - action.performAction(changeListener); - } - - - } - - } - } - } - } - - public void removeDispositionListener(Method method) - { - _messageDispositionListenerMap.remove(method.getId()); - } - - public void onClose() - { - if(_transaction instanceof LocalTransaction) - { - _transaction.rollback(); - } - else if(_transaction instanceof DistributedTransaction) - { - getVirtualHost().getDtxRegistry().endAssociations(this); - } - - for(MessageDispositionChangeListener listener : _messageDispositionListenerMap.values()) - { - listener.onRelease(true); - } - _messageDispositionListenerMap.clear(); - - for (Task task : _taskList) - { - task.doTask(this); - } - - LogMessage operationalLoggingMessage = _forcedCloseLogMessage.get(); - if (operationalLoggingMessage == null) - { - operationalLoggingMessage = ChannelMessages.CLOSE(); - } - CurrentActor.get().message(getLogSubject(), operationalLoggingMessage); - } - - @Override - protected void awaitClose() - { - // Broker shouldn't block awaiting close - thus do override this method to do nothing - } - - public void acknowledge(final Subscription_0_10 sub, final QueueEntry entry) - { - _transaction.dequeue(entry.getQueue(), entry.getMessage(), - new ServerTransaction.Action() - { - - public void postCommit() - { - sub.acknowledge(entry); - } - - public void onRollback() - { - // The client has acknowledge the message and therefore have seen it. - // In the event of rollback, the message must be marked as redelivered. - entry.setRedelivered(); - entry.release(); - } - }); - } - - public Collection getSubscriptions() - { - return _subscriptions.values(); - } - - public void register(String destination, Subscription_0_10 sub) - { - _subscriptions.put(destination == null ? NULL_DESTINTATION : destination, sub); - } - - public Subscription_0_10 getSubscription(String destination) - { - return _subscriptions.get(destination == null ? NULL_DESTINTATION : destination); - } - - public void unregister(Subscription_0_10 sub) - { - _subscriptions.remove(sub.getName()); - try - { - sub.getSendLock(); - AMQQueue queue = sub.getQueue(); - if(queue != null) - { - queue.unregisterSubscription(sub); - } - } - catch (AMQException e) - { - // TODO - _logger.error("Failed to unregister subscription :" + e.getMessage(), e); - } - finally - { - sub.releaseSendLock(); - } - } - - public boolean isTransactional() - { - return _transaction.isTransactional(); - } - - public void selectTx() - { - _transaction = new LocalTransaction(this.getMessageStore()); - _txnStarts.incrementAndGet(); - } - - public void selectDtx() - { - _transaction = new DistributedTransaction(this, getMessageStore(), getVirtualHost()); - - } - - - public void startDtx(Xid xid, boolean join, boolean resume) - throws JoinAndResumeDtxException, - UnknownDtxBranchException, - AlreadyKnownDtxException, - DtxNotSelectedException - { - DistributedTransaction distributedTransaction = assertDtxTransaction(); - distributedTransaction.start(xid, join, resume); - } - - - public void endDtx(Xid xid, boolean fail, boolean suspend) - throws NotAssociatedDtxException, - UnknownDtxBranchException, - DtxNotSelectedException, - SuspendAndFailDtxException, TimeoutDtxException - { - DistributedTransaction distributedTransaction = assertDtxTransaction(); - distributedTransaction.end(xid, fail, suspend); - } - - - public long getTimeoutDtx(Xid xid) - throws UnknownDtxBranchException - { - return getVirtualHost().getDtxRegistry().getTimeout(xid); - } - - - public void setTimeoutDtx(Xid xid, long timeout) - throws UnknownDtxBranchException - { - getVirtualHost().getDtxRegistry().setTimeout(xid, timeout); - } - - - public void prepareDtx(Xid xid) - throws UnknownDtxBranchException, - IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException - { - getVirtualHost().getDtxRegistry().prepare(xid); - } - - public void commitDtx(Xid xid, boolean onePhase) - throws UnknownDtxBranchException, - IncorrectDtxStateException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException - { - getVirtualHost().getDtxRegistry().commit(xid, onePhase); - } - - - public void rollbackDtx(Xid xid) - throws UnknownDtxBranchException, - IncorrectDtxStateException, AMQStoreException, TimeoutDtxException - { - getVirtualHost().getDtxRegistry().rollback(xid); - } - - - public void forgetDtx(Xid xid) throws UnknownDtxBranchException, IncorrectDtxStateException - { - getVirtualHost().getDtxRegistry().forget(xid); - } - - public List recoverDtx() - { - return getVirtualHost().getDtxRegistry().recover(); - } - - private DistributedTransaction assertDtxTransaction() throws DtxNotSelectedException - { - if(_transaction instanceof DistributedTransaction) - { - return (DistributedTransaction) _transaction; - } - else - { - throw new DtxNotSelectedException(); - } - } - - - public void commit() - { - _transaction.commit(); - - _txnCommits.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); - } - - public void rollback() - { - _transaction.rollback(); - - _txnRejects.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); - } - - - private void incrementOutstandingTxnsIfNecessary() - { - if(isTransactional()) - { - //There can currently only be at most one outstanding transaction - //due to only having LocalTransaction support. Set value to 1 if 0. - _txnCount.compareAndSet(0,1); - } - } - - private void decrementOutstandingTxnsIfNecessary() - { - if(isTransactional()) - { - //There can currently only be at most one outstanding transaction - //due to only having LocalTransaction support. Set value to 0 if 1. - _txnCount.compareAndSet(1,0); - } - } - - public Long getTxnCommits() - { - return _txnCommits.get(); - } - - public Long getTxnRejects() - { - return _txnRejects.get(); - } - - public int getChannelId() - { - return getChannel(); - } - - public Long getTxnCount() - { - return _txnCount.get(); - } - - public Long getTxnStart() - { - return _txnStarts.get(); - } - - public Principal getAuthorizedPrincipal() - { - return getConnection().getAuthorizedPrincipal(); - } - - public Subject getAuthorizedSubject() - { - return getConnection().getAuthorizedSubject(); - } - - public void addSessionCloseTask(Task task) - { - _taskList.add(task); - } - - public void removeSessionCloseTask(Task task) - { - _taskList.remove(task); - } - - public Object getReference() - { - return getConnection().getReference(); - } - - public MessageStore getMessageStore() - { - return getVirtualHost().getMessageStore(); - } - - public VirtualHost getVirtualHost() - { - return getConnection().getVirtualHost(); - } - - public boolean isDurable() - { - return false; - } - - - public long getCreateTime() - { - return _createTime; - } - - @Override - public UUID getId() - { - return _id; - } - - public AMQConnectionModel getConnectionModel() - { - return getConnection(); - } - - public String getClientID() - { - return getConnection().getClientId(); - } - - @Override - public ServerConnection getConnection() - { - return (ServerConnection) super.getConnection(); - } - - public LogActor getLogActor() - { - return _actor; - } - - public LogSubject getLogSubject() - { - return (LogSubject) this; - } - - public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException - { - _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); - } - - public void block(AMQQueue queue) - { - block(queue, queue.getName()); - } - - public void block() - { - block(this, "** All Queues **"); - } - - - private void block(Object queue, String name) - { - synchronized (_blockingEntities) - { - if(_blockingEntities.add(queue)) - { - - if(_blocking.compareAndSet(false,true)) - { - if(getState() == State.OPEN) - { - invokeBlock(); - } - _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(name)); - } - - - } - } - } - - public void unblock(AMQQueue queue) - { - unblock((Object)queue); - } - - public void unblock() - { - unblock(this); - } - - private void unblock(Object queue) - { - synchronized(_blockingEntities) - { - if(_blockingEntities.remove(queue) && _blockingEntities.isEmpty()) - { - if(_blocking.compareAndSet(true,false) && !isClosing()) - { - - _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); - MessageFlow mf = new MessageFlow(); - mf.setUnit(MessageCreditUnit.MESSAGE); - mf.setDestination(""); - _outstandingCredit.set(Integer.MAX_VALUE); - mf.setValue(Integer.MAX_VALUE); - invoke(mf); - - - } - } - } - } - - public boolean onSameConnection(InboundMessage inbound) - { - return ((inbound instanceof MessageTransferMessage) - && ((MessageTransferMessage)inbound).getConnectionReference() == getConnection().getReference()) - || ((inbound instanceof MessageMetaData_0_10) - && (((MessageMetaData_0_10)inbound).getConnectionReference())== getConnection().getReference()); - } - - - public String toLogString() - { - long connectionId = super.getConnection() instanceof ServerConnection - ? getConnection().getConnectionId() - : -1; - - String remoteAddress = String.valueOf(getConnection().getRemoteAddress()); - return "[" + - MessageFormat.format(CHANNEL_FORMAT, - connectionId, - getClientID(), - remoteAddress, - getVirtualHost().getName(), - getChannel()) - + "] "; - } - - @Override - public void close(AMQConstant cause, String message) - { - if (cause == null) - { - close(); - } - else - { - close(cause.getCode(), message); - } - } - - void close(int cause, String message) - { - _forcedCloseLogMessage.compareAndSet(null, ChannelMessages.CLOSE_FORCED(cause, message)); - close(); - } - - @Override - public void close() - { - // unregister subscriptions in order to prevent sending of new messages - // to subscriptions with closing session - unregisterSubscriptions(); - super.close(); - } - - void unregisterSubscriptions() - { - final Collection subscriptions = getSubscriptions(); - for (Subscription_0_10 subscription_0_10 : subscriptions) - { - unregister(subscription_0_10); - } - } - - void stopSubscriptions() - { - final Collection subscriptions = getSubscriptions(); - for (Subscription_0_10 subscription_0_10 : subscriptions) - { - subscription_0_10.stop(); - } - } - - - public void receivedComplete() - { - final Collection subscriptions = getSubscriptions(); - for (Subscription_0_10 subscription_0_10 : subscriptions) - { - subscription_0_10.flushCreditState(false); - } - awaitCommandCompletion(); - } - - private class PostEnqueueAction implements ServerTransaction.Action - { - - private List _queues; - private ServerMessage _message; - private final boolean _transactional; - - public PostEnqueueAction(List queues, ServerMessage message, final boolean transactional) - { - _transactional = transactional; - setState(queues, message); - } - - public void setState(List queues, ServerMessage message) - { - _message = message; - _queues = queues; - } - - public void postCommit() - { - MessageReference ref = _message.newReference(); - for(int i = 0; i < _queues.size(); i++) - { - try - { - BaseQueue queue = _queues.get(i); - queue.enqueue(_message, _transactional, null); - if(queue instanceof AMQQueue) - { - ((AMQQueue)queue).checkCapacity(ServerSession.this); - } - - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - } - ref.release(); - } - - public void onRollback() - { - // NO-OP - } - } - - public int getUnacknowledgedMessageCount() - { - return _messageDispositionListenerMap.size(); - } - - public boolean getBlocking() - { - return _blocking.get(); - } - - private final LinkedList _unfinishedCommandsQueue = new LinkedList(); - - public void completeAsyncCommands() - { - AsyncCommand cmd; - while((cmd = _unfinishedCommandsQueue.peek()) != null && cmd.isReadyForCompletion()) - { - cmd.complete(); - _unfinishedCommandsQueue.poll(); - } - while(_unfinishedCommandsQueue.size() > UNFINISHED_COMMAND_QUEUE_THRESHOLD) - { - cmd = _unfinishedCommandsQueue.poll(); - cmd.awaitReadyForCompletion(); - cmd.complete(); - } - } - - - public void awaitCommandCompletion() - { - AsyncCommand cmd; - while((cmd = _unfinishedCommandsQueue.poll()) != null) - { - cmd.awaitReadyForCompletion(); - cmd.complete(); - } - } - - - public Object getAsyncCommandMark() - { - return _unfinishedCommandsQueue.isEmpty() ? null : _unfinishedCommandsQueue.getLast(); - } - - public void recordFuture(final StoreFuture future, final ServerTransaction.Action action) - { - _unfinishedCommandsQueue.add(new AsyncCommand(future, action)); - } - - private static class AsyncCommand - { - private final StoreFuture _future; - private ServerTransaction.Action _action; - - public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action) - { - _future = future; - _action = action; - } - - void awaitReadyForCompletion() - { - _future.waitForCompletion(); - } - - void complete() - { - if(!_future.isComplete()) - { - _future.waitForCompletion(); - } - _action.postCommit(); - _action = null; - } - - boolean isReadyForCompletion() - { - return _future.isComplete(); - } - } - - protected void setClose(boolean close) - { - super.setClose(close); - } - - @Override - public int getConsumerCount() - { - return _subscriptions.values().size(); - } - - @Override - public int compareTo(AMQSessionModel o) - { - return getId().compareTo(o.getId()); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java deleted file mode 100644 index b7ac86795d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ /dev/null @@ -1,1590 +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.transport; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQStoreException; -import org.apache.qpid.AMQUnknownExchangeType; -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.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeInUseException; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.HeadersExchange; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.filter.FilterManagerFactory; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.flow.WindowCreditManager; -import org.apache.qpid.server.logging.messages.ExchangeMessages; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.DurableConfigurationStoreHelper; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.txn.AlreadyKnownDtxException; -import org.apache.qpid.server.txn.DtxNotSelectedException; -import org.apache.qpid.server.txn.IncorrectDtxStateException; -import org.apache.qpid.server.txn.JoinAndResumeDtxException; -import org.apache.qpid.server.txn.NotAssociatedDtxException; -import org.apache.qpid.server.txn.RollbackOnlyDtxException; -import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.txn.SuspendAndFailDtxException; -import org.apache.qpid.server.txn.TimeoutDtxException; -import org.apache.qpid.server.txn.UnknownDtxBranchException; -import org.apache.qpid.server.virtualhost.ExchangeExistsException; -import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; -import org.apache.qpid.server.virtualhost.RequiredExchangeException; -import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; -import org.apache.qpid.server.virtualhost.UnknownExchangeException; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.*; - -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -public class ServerSessionDelegate extends SessionDelegate -{ - private static final Logger LOGGER = Logger.getLogger(ServerSessionDelegate.class); - - /** - * No-local queue argument is used to support the no-local feature of Durable Subscribers. - */ - private static final String QUEUE_ARGUMENT_NO_LOCAL = "no-local"; - - public ServerSessionDelegate() - { - - } - - @Override - public void command(Session session, Method method) - { - try - { - setThreadSubject(session); - - if(!session.isClosing()) - { - Object asyncCommandMark = ((ServerSession)session).getAsyncCommandMark(); - super.command(session, method, false); - Object newOutstanding = ((ServerSession)session).getAsyncCommandMark(); - if(newOutstanding == null || newOutstanding == asyncCommandMark) - { - session.processed(method); - } - - if(newOutstanding != null) - { - ((ServerSession)session).completeAsyncCommands(); - } - - if (method.isSync()) - { - ((ServerSession)session).awaitCommandCompletion(); - session.flushProcessed(); - } - } - } - catch(RuntimeException e) - { - LOGGER.error("Exception processing command", e); - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Exception processing command: " + e); - } - } - - @Override - public void messageAccept(Session session, MessageAccept method) - { - final ServerSession serverSession = (ServerSession) session; - serverSession.accept(method.getTransfers()); - if(!serverSession.isTransactional()) - { - serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE, - new CommandProcessedAction(serverSession, method)); - } - } - - @Override - public void messageReject(Session session, MessageReject method) - { - ((ServerSession)session).reject(method.getTransfers()); - } - - @Override - public void messageRelease(Session session, MessageRelease method) - { - ((ServerSession)session).release(method.getTransfers(), method.getSetRedelivered()); - } - - @Override - public void messageAcquire(Session session, MessageAcquire method) - { - RangeSet acquiredRanges = ((ServerSession)session).acquire(method.getTransfers()); - - Acquired result = new Acquired(acquiredRanges); - - - session.executionResult((int) method.getId(), result); - - - } - - @Override - public void messageResume(Session session, MessageResume method) - { - super.messageResume(session, method); - } - - @Override - public void messageSubscribe(Session session, MessageSubscribe method) - { - /* - TODO - work around broken Python tests - Correct code should read like - if not hasAcceptMode() exception ILLEGAL_ARGUMENT "Accept-mode not supplied" - else if not method.hasAcquireMode() exception ExecutionErrorCode.ILLEGAL_ARGUMENT, "Acquire-mode not supplied" - */ - if(!method.hasAcceptMode()) - { - method.setAcceptMode(MessageAcceptMode.EXPLICIT); - } - if(!method.hasAcquireMode()) - { - method.setAcquireMode(MessageAcquireMode.PRE_ACQUIRED); - - } - - if(!method.hasQueue()) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not supplied"); - } - else - { - String destination = method.getDestination(); - - if(((ServerSession)session).getSubscription(destination)!=null) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Subscription already exists with destination '"+destination+"'"); - } - else - { - String queueName = method.getQueue(); - QueueRegistry queueRegistry = getQueueRegistry(session); - - - final AMQQueue queue = queueRegistry.getQueue(queueName); - - if(queue == null) - { - exception(session,method,ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found"); - } - else if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session) - { - exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); - } - else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session) - { - exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); - } - else - { - if(queue.isExclusive()) - { - ServerSession s = (ServerSession) session; - queue.setExclusiveOwningSession(s); - if(queue.getAuthorizationHolder() == null) - { - queue.setAuthorizationHolder(s); - queue.setExclusiveOwningSession(s); - ((ServerSession) session).addSessionCloseTask(new ServerSession.Task() - { - public void doTask(ServerSession session) - { - if(queue.getAuthorizationHolder() == session) - { - queue.setAuthorizationHolder(null); - queue.setExclusiveOwningSession(null); - } - } - }); - } - } - - FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L); - - FilterManager filterManager = null; - try - { - filterManager = FilterManagerFactory.createManager(method.getArguments()); - } - catch (AMQException amqe) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Exception Creating FilterManager"); - return; - } - - Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session, - destination, - method.getAcceptMode(), - method.getAcquireMode(), - MessageFlowMode.WINDOW, - creditManager, - filterManager, - method.getArguments()); - - ((ServerSession)session).register(destination, sub); - try - { - queue.registerSubscription(sub, method.getExclusive()); - } - catch (AMQQueue.ExistingExclusiveSubscription existing) - { - exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an exclusive consumer"); - } - catch (AMQQueue.ExistingSubscriptionPreventsExclusive exclusive) - { - exception(session, method, ExecutionErrorCode.RESOURCE_LOCKED, "Queue has an existing consumer - can't subscribe exclusively"); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot subscribe to queue '" + queueName + "' with destination '" + destination); - } - } - } - } - } - - @Override - public void messageTransfer(Session ssn, final MessageTransfer xfr) - { - final Exchange exchange = getExchangeForMessage(ssn, xfr); - - DeliveryProperties delvProps = null; - if(xfr.getHeader() != null && (delvProps = xfr.getHeader().getDeliveryProperties()) != null && delvProps.hasTtl() && !delvProps - .hasExpiration()) - { - delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); - } - - final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); - messageMetaData.setConnectionReference(((ServerSession)ssn).getReference()); - - if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName())) - { - ExecutionErrorCode errorCode = ExecutionErrorCode.UNAUTHORIZED_ACCESS; - String description = "Permission denied: exchange-name '" + exchange.getName() + "'"; - exception(ssn, xfr, errorCode, description); - - return; - } - - final Exchange exchangeInUse; - List queues = exchange.route(messageMetaData); - if(queues.isEmpty() && exchange.getAlternateExchange() != null) - { - final Exchange alternateExchange = exchange.getAlternateExchange(); - queues = alternateExchange.route(messageMetaData); - if (!queues.isEmpty()) - { - exchangeInUse = alternateExchange; - } - else - { - exchangeInUse = exchange; - } - } - else - { - exchangeInUse = exchange; - } - - final ServerSession serverSession = (ServerSession) ssn; - if(!queues.isEmpty()) - { - final MessageStore store = getVirtualHost(ssn).getMessageStore(); - final StoredMessage storeMessage = createStoreMessage(xfr, messageMetaData, store); - MessageTransferMessage message = new MessageTransferMessage(storeMessage, serverSession.getReference()); - serverSession.enqueue(message, queues); - storeMessage.flushToStore(); - } - else - { - if((delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) - { - RangeSet rejects = RangeSetFactory.createRangeSet(); - rejects.add(xfr.getId()); - MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); - ssn.invoke(reject); - } - else - { - serverSession.getLogActor().message(ExchangeMessages.DISCARDMSG(exchangeInUse.getName(), messageMetaData.getRoutingKey())); - } - } - - - if(serverSession.isTransactional()) - { - serverSession.processed(xfr); - } - else - { - serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE, new CommandProcessedAction(serverSession, xfr)); - } - } - - private StoredMessage createStoreMessage(final MessageTransfer xfr, - final MessageMetaData_0_10 messageMetaData, final MessageStore store) - { - final StoredMessage storeMessage = store.addMessage(messageMetaData); - ByteBuffer body = xfr.getBody(); - if(body != null) - { - storeMessage.addContent(0, body); - } - return storeMessage; - } - - @Override - public void messageCancel(Session session, MessageCancel method) - { - String destination = method.getDestination(); - - Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); - - if(sub == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); - } - else - { - AMQQueue queue = sub.getQueue(); - ((ServerSession)session).unregister(sub); - if(!queue.isDeleted() && queue.isExclusive() && queue.getConsumerCount() == 0) - { - queue.setAuthorizationHolder(null); - } - } - } - - @Override - public void messageFlush(Session session, MessageFlush method) - { - String destination = method.getDestination(); - - Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); - - if(sub == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); - } - else - { - - try - { - sub.flush(); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot flush subscription '" + destination); - } - } - } - - @Override - public void txSelect(Session session, TxSelect method) - { - // TODO - check current tx mode - ((ServerSession)session).selectTx(); - } - - @Override - public void txCommit(Session session, TxCommit method) - { - // TODO - check current tx mode - ((ServerSession)session).commit(); - } - - @Override - public void txRollback(Session session, TxRollback method) - { - // TODO - check current tx mode - ((ServerSession)session).rollback(); - } - - @Override - public void dtxSelect(Session session, DtxSelect method) - { - // TODO - check current tx mode - ((ServerSession)session).selectDtx(); - } - - @Override - public void dtxStart(Session session, DtxStart method) - { - XaResult result = new XaResult(); - result.setStatus(DtxXaStatus.XA_OK); - try - { - ((ServerSession)session).startDtx(method.getXid(), method.getJoin(), method.getResume()); - session.executionResult(method.getId(), result); - } - catch(JoinAndResumeDtxException e) - { - exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Unknown xid " + method.getXid()); - } - catch(AlreadyKnownDtxException e) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Xid already started an neither join nor " + - "resume set" + method.getXid()); - } - catch(DtxNotSelectedException e) - { - exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); - } - - } - - @Override - public void dtxEnd(Session session, DtxEnd method) - { - XaResult result = new XaResult(); - result.setStatus(DtxXaStatus.XA_OK); - try - { - try - { - ((ServerSession)session).endDtx(method.getXid(), method.getFail(), method.getSuspend()); - } - catch (TimeoutDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBTIMEOUT); - } - session.executionResult(method.getId(), result); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(NotAssociatedDtxException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(DtxNotSelectedException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(SuspendAndFailDtxException e) - { - exception(session, method, ExecutionErrorCode.COMMAND_INVALID, e.getMessage()); - } - - } - - @Override - public void dtxCommit(Session session, DtxCommit method) - { - XaResult result = new XaResult(); - result.setStatus(DtxXaStatus.XA_OK); - try - { - try - { - ((ServerSession)session).commitDtx(method.getXid(), method.getOnePhase()); - } - catch (RollbackOnlyDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBROLLBACK); - } - catch (TimeoutDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBTIMEOUT); - } - session.executionResult(method.getId(), result); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - catch(IncorrectDtxStateException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(AMQStoreException e) - { - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } - - @Override - public void dtxForget(Session session, DtxForget method) - { - try - { - ((ServerSession)session).forgetDtx(method.getXid()); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - catch(IncorrectDtxStateException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - - } - - @Override - public void dtxGetTimeout(Session session, DtxGetTimeout method) - { - GetTimeoutResult result = new GetTimeoutResult(); - try - { - result.setTimeout(((ServerSession) session).getTimeoutDtx(method.getXid())); - session.executionResult(method.getId(), result); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - } - - @Override - public void dtxPrepare(Session session, DtxPrepare method) - { - XaResult result = new XaResult(); - result.setStatus(DtxXaStatus.XA_OK); - try - { - try - { - ((ServerSession)session).prepareDtx(method.getXid()); - } - catch (RollbackOnlyDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBROLLBACK); - } - catch (TimeoutDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBTIMEOUT); - } - session.executionResult((int) method.getId(), result); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - catch(IncorrectDtxStateException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(AMQStoreException e) - { - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } - - @Override - public void dtxRecover(Session session, DtxRecover method) - { - RecoverResult result = new RecoverResult(); - List inDoubt = ((ServerSession)session).recoverDtx(); - result.setInDoubt(inDoubt); - session.executionResult(method.getId(), result); - } - - @Override - public void dtxRollback(Session session, DtxRollback method) - { - - XaResult result = new XaResult(); - result.setStatus(DtxXaStatus.XA_OK); - try - { - try - { - ((ServerSession)session).rollbackDtx(method.getXid()); - } - catch (TimeoutDtxException e) - { - result.setStatus(DtxXaStatus.XA_RBTIMEOUT); - } - session.executionResult(method.getId(), result); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - catch(IncorrectDtxStateException e) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_STATE, e.getMessage()); - } - catch(AMQStoreException e) - { - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, e.getMessage()); - } - } - - @Override - public void dtxSetTimeout(Session session, DtxSetTimeout method) - { - try - { - ((ServerSession)session).setTimeoutDtx(method.getXid(), method.getTimeout()); - } - catch(UnknownDtxBranchException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, e.getMessage()); - } - } - - @Override - public void executionSync(final Session ssn, final ExecutionSync sync) - { - ((ServerSession)ssn).awaitCommandCompletion(); - super.executionSync(ssn, sync); - } - - @Override - public void exchangeDeclare(Session session, ExchangeDeclare method) - { - String exchangeName = method.getExchange(); - VirtualHost virtualHost = getVirtualHost(session); - - //we must check for any unsupported arguments present and throw not-implemented - if(method.hasArguments()) - { - Map args = method.getArguments(); - //QPID-3392: currently we don't support any! - if(!args.isEmpty()) - { - exception(session, method, ExecutionErrorCode.NOT_IMPLEMENTED, "Unsupported exchange argument(s) found " + args.keySet().toString()); - return; - } - } - - if(method.getPassive()) - { - Exchange exchange = getExchange(session, exchangeName); - - if(exchange == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "not-found: exchange-name '" + exchangeName + "'"); - } - else - { - if (!exchange.getTypeShortString().toString().equals(method.getType()) - && (method.getType() != null && method.getType().length() > 0)) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " - + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() + "."); - } - } - } - else - { - - try - { - virtualHost.createExchange(null, - method.getExchange(), - method.getType(), - method.getDurable(), - method.getAutoDelete(), - method.getAlternateExchange()); - } - catch(ReservedExchangeNameException e) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to declare exchange: " - + exchangeName + " which begins with reserved name or prefix."); - } - catch(UnknownExchangeException e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, - "Unknown alternate exchange " + e.getExchangeName()); - } - catch(AMQUnknownExchangeType e) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "Unknown Exchange Type: " + method.getType()); - } - catch(ExchangeExistsException e) - { - Exchange exchange = e.getExistingExchange(); - if(!exchange.getTypeShortString().toString().equals(method.getType())) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, - "Attempt to redeclare exchange: " + exchangeName - + " of type " + exchange.getTypeShortString() - + " to " + method.getType() +"."); - } - else if(method.hasAlternateExchange() - && (exchange.getAlternateExchange() == null || - !method.getAlternateExchange().equals(exchange.getAlternateExchange().getName()))) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, - "Attempt to change alternate exchange of: " + exchangeName - + " from " + exchange.getAlternateExchange() - + " to " + method.getAlternateExchange() +"."); - } - } - catch (AMQException e) - { - exception(session, method, e, "Cannot declare exchange '" + exchangeName); - } - - - } - - } - - // TODO decouple AMQException and AMQConstant error codes - private void exception(Session session, Method method, AMQException exception, String message) - { - ExecutionErrorCode errorCode = ExecutionErrorCode.INTERNAL_ERROR; - if (exception.getErrorCode() != null) - { - try - { - errorCode = ExecutionErrorCode.get(exception.getErrorCode().getCode()); - } - catch (IllegalArgumentException iae) - { - // ignore, already set to INTERNAL_ERROR - } - } - String description = message + "': " + exception.getMessage(); - - exception(session, method, errorCode, description); - } - - private void exception(Session session, Method method, ExecutionErrorCode errorCode, String description) - { - ExecutionException ex = new ExecutionException(); - ex.setErrorCode(errorCode); - ex.setCommandId(method.getId()); - ex.setDescription(description); - - session.invoke(ex); - - ((ServerSession)session).close(errorCode.getValue(), description); - } - - private Exchange getExchange(Session session, String exchangeName) - { - return getVirtualHost(session).getExchange(exchangeName); - } - - private Exchange getExchangeForMessage(Session ssn, MessageTransfer xfr) - { - VirtualHost virtualHost = getVirtualHost(ssn); - - Exchange exchange; - if(xfr.hasDestination()) - { - exchange = virtualHost.getExchange(xfr.getDestination()); - if(exchange == null) - { - exchange = virtualHost.getDefaultExchange(); - } - } - else - { - exchange = virtualHost.getDefaultExchange(); - } - return exchange; - } - - private VirtualHost getVirtualHost(Session session) - { - ServerConnection conn = getServerConnection(session); - VirtualHost vhost = conn.getVirtualHost(); - return vhost; - } - - private ServerConnection getServerConnection(Session session) - { - ServerConnection conn = (ServerConnection) session.getConnection(); - return conn; - } - - @Override - public void exchangeDelete(Session session, ExchangeDelete method) - { - VirtualHost virtualHost = getVirtualHost(session); - - try - { - if (nameNullOrEmpty(method.getExchange())) - { - exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Delete not allowed for default exchange"); - return; - } - - Exchange exchange = getExchange(session, method.getExchange()); - - if(exchange == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "No such exchange '" + method.getExchange() + "'"); - } - else - { - virtualHost.removeExchange(exchange, !method.getIfUnused()); - } - } - catch (ExchangeInUseException e) - { - exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Exchange in use"); - } - catch (ExchangeIsAlternateException e) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Exchange in use as an alternate exchange"); - } - catch (RequiredExchangeException e) - { - exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Exchange '"+method.getExchange()+"' cannot be deleted"); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot delete exchange '" + method.getExchange() ); - } - } - - private boolean nameNullOrEmpty(String name) - { - if(name == null || name.length() == 0) - { - return true; - } - - return false; - } - - private boolean isStandardExchange(Exchange exchange, Collection> registeredTypes) - { - for(ExchangeType type : registeredTypes) - { - if(type.getDefaultExchangeName().toString().equals( exchange.getName() )) - { - return true; - } - } - return false; - } - - @Override - public void exchangeQuery(Session session, ExchangeQuery method) - { - - ExchangeQueryResult result = new ExchangeQueryResult(); - - Exchange exchange = getExchange(session, method.getName()); - - if(exchange != null) - { - result.setDurable(exchange.isDurable()); - result.setType(exchange.getTypeShortString().toString()); - result.setNotFound(false); - } - else - { - result.setNotFound(true); - } - - session.executionResult((int) method.getId(), result); - } - - @Override - public void exchangeBind(Session session, ExchangeBind method) - { - - VirtualHost virtualHost = getVirtualHost(session); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - - if (!method.hasQueue()) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set"); - } - else if (nameNullOrEmpty(method.getExchange())) - { - exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Bind not allowed for default exchange"); - } - else - { - //TODO - here because of non-compiant python tests - // should raise exception ILLEGAL_ARGUMENT "binding-key not set" - if (!method.hasBindingKey()) - { - method.setBindingKey(method.getQueue()); - } - AMQQueue queue = queueRegistry.getQueue(method.getQueue()); - Exchange exchange = virtualHost.getExchange(method.getExchange()); - if(queue == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found"); - } - else if(exchange == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found"); - } - else if(exchange.getTypeShortString().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) - { - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getName() + " require an x-match header"); - } - else - { - if (!exchange.isBound(method.getBindingKey(), method.getArguments(), queue)) - { - try - { - exchange.addBinding(method.getBindingKey(), queue, method.getArguments()); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot add binding '" + method.getBindingKey()); - } - } - else - { - // todo - } - } - - - } - - - - } - - @Override - public void exchangeUnbind(Session session, ExchangeUnbind method) - { - VirtualHost virtualHost = getVirtualHost(session); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - - if (!method.hasQueue()) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set"); - } - else if (nameNullOrEmpty(method.getExchange())) - { - exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Unbind not allowed for default exchange"); - } - else if (!method.hasBindingKey()) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "binding-key not set"); - } - else - { - AMQQueue queue = queueRegistry.getQueue(method.getQueue()); - Exchange exchange = virtualHost.getExchange(method.getExchange()); - if(queue == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "Queue: '" + method.getQueue() + "' not found"); - } - else if(exchange == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found"); - } - else - { - try - { - exchange.removeBinding(method.getBindingKey(), queue, null); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot remove binding '" + method.getBindingKey()); - } - } - } - } - - @Override - public void exchangeBound(Session session, ExchangeBound method) - { - - ExchangeBoundResult result = new ExchangeBoundResult(); - VirtualHost virtualHost = getVirtualHost(session); - Exchange exchange; - AMQQueue queue; - if(method.hasExchange()) - { - exchange = virtualHost.getExchange(method.getExchange()); - - if(exchange == null) - { - result.setExchangeNotFound(true); - } - } - else - { - exchange = virtualHost.getDefaultExchange(); - } - - - if(method.hasQueue()) - { - - queue = getQueue(session, method.getQueue()); - if(queue == null) - { - result.setQueueNotFound(true); - } - - - if(exchange != null && queue != null) - { - - boolean queueMatched = exchange.isBound(queue); - - result.setQueueNotMatched(!queueMatched); - - - if(method.hasBindingKey()) - { - - if(queueMatched) - { - final boolean keyMatched = exchange.isBound(method.getBindingKey(), queue); - result.setKeyNotMatched(!keyMatched); - if(method.hasArguments()) - { - if(keyMatched) - { - result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments(), queue)); - } - else - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments(), queue)); - } - } - } - else - { - boolean keyMatched = exchange.isBound(method.getBindingKey()); - result.setKeyNotMatched(!keyMatched); - if(method.hasArguments()) - { - if(keyMatched) - { - result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); - } - else - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments())); - } - } - } - - } - else if (method.hasArguments()) - { - if(queueMatched) - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments(), queue)); - } - else - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments())); - } - } - - } - else if(exchange != null && method.hasBindingKey()) - { - final boolean keyMatched = exchange.isBound(method.getBindingKey()); - result.setKeyNotMatched(!keyMatched); - - if(method.hasArguments()) - { - if(keyMatched) - { - result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); - } - else - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments())); - } - } - - - } - - } - else if(exchange != null && method.hasBindingKey()) - { - final boolean keyMatched = exchange.isBound(method.getBindingKey()); - result.setKeyNotMatched(!keyMatched); - - if(method.hasArguments()) - { - if(keyMatched) - { - result.setArgsNotMatched(!exchange.isBound(method.getBindingKey(), method.getArguments())); - } - else - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments())); - } - } - - } - else if(exchange != null && method.hasArguments()) - { - result.setArgsNotMatched(!exchange.isBound(method.getArguments())); - } - - - session.executionResult((int) method.getId(), result); - - - } - - private AMQQueue getQueue(Session session, String queue) - { - QueueRegistry queueRegistry = getQueueRegistry(session); - return queueRegistry.getQueue(queue); - } - - private QueueRegistry getQueueRegistry(Session session) - { - return getVirtualHost(session).getQueueRegistry(); - } - - @Override - public void queueDeclare(Session session, final QueueDeclare method) - { - - VirtualHost virtualHost = getVirtualHost(session); - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - - String queueName = method.getQueue(); - AMQQueue queue; - QueueRegistry queueRegistry = getQueueRegistry(session); - //TODO: do we need to check that the queue already exists with exactly the same "configuration"? - - synchronized (queueRegistry) - { - - if (((queue = queueRegistry.getQueue(queueName)) == null)) - { - - if (method.getPassive()) - { - String description = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; - ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_FOUND; - - exception(session, method, errorCode, description); - - return; - } - else - { - try - { - queue = createQueue(queueName, method, virtualHost, (ServerSession)session); - if(!method.getExclusive() && method.getAutoDelete()) - { - queue.setDeleteOnNoConsumers(true); - } - - final String alternateExchangeName = method.getAlternateExchange(); - if(alternateExchangeName != null && alternateExchangeName.length() != 0) - { - Exchange alternate = getExchange(session, alternateExchangeName); - queue.setAlternateExchange(alternate); - } - - if(method.hasArguments() && method.getArguments() != null) - { - if(method.getArguments().containsKey(QUEUE_ARGUMENT_NO_LOCAL)) - { - Object noLocal = method.getArguments().get(QUEUE_ARGUMENT_NO_LOCAL); - queue.setNoLocal(convertBooleanValue(noLocal)); - } - } - - - if (queue.isDurable() && !queue.isAutoDelete()) - { - if(method.hasArguments() && method.getArguments() != null) - { - Map args = method.getArguments(); - FieldTable ftArgs = new FieldTable(); - for(Map.Entry entry : args.entrySet()) - { - ftArgs.put(new AMQShortString(entry.getKey()), entry.getValue()); - } - DurableConfigurationStoreHelper.createQueue(store, queue, ftArgs); - } - else - { - DurableConfigurationStoreHelper.createQueue(store, queue, null); - } - } - queueRegistry.registerQueue(queue); - - if (method.hasAutoDelete() - && method.getAutoDelete() - && method.hasExclusive() - && method.getExclusive()) - { - final AMQQueue q = queue; - final ServerSession.Task deleteQueueTask = new ServerSession.Task() - { - public void doTask(ServerSession session) - { - try - { - q.delete(); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot delete '" + method.getQueue()); - } - } - }; - final ServerSession s = (ServerSession) session; - s.addSessionCloseTask(deleteQueueTask); - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) throws AMQException - { - s.removeSessionCloseTask(deleteQueueTask); - } - }); - } - if (method.hasExclusive() - && method.getExclusive()) - { - final AMQQueue q = queue; - final ServerSession.Task removeExclusive = new ServerSession.Task() - { - public void doTask(ServerSession session) - { - q.setAuthorizationHolder(null); - q.setExclusiveOwningSession(null); - } - }; - final ServerSession s = (ServerSession) session; - q.setExclusiveOwningSession(s); - s.addSessionCloseTask(removeExclusive); - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) throws AMQException - { - s.removeSessionCloseTask(removeExclusive); - } - }); - } - } - catch (AMQException e) - { - exception(session, method, e, "Cannot declare queue '" + queueName); - } - } - } - else if (method.getExclusive() && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session))) - { - String description = "Cannot declare queue('" + queueName + "')," - + " as exclusive queue with same name " - + "declared on another session"; - ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED; - - exception(session, method, errorCode, description); - - return; - } - } - } - - /** - * Converts a queue argument into a boolean value. For compatibility with the C++ - * and the clients, accepts with Boolean, String, or Number types. - * @param argValue argument value. - * - * @return true if set - */ - private boolean convertBooleanValue(Object argValue) - { - if(argValue instanceof Boolean && ((Boolean)argValue)) - { - return true; - } - else if (argValue instanceof String && Boolean.parseBoolean((String)argValue)) - { - return true; - } - else if (argValue instanceof Number && ((Number)argValue).intValue() != 0) - { - return true; - } - return false; - } - - protected AMQQueue createQueue(final String queueName, - final QueueDeclare body, - VirtualHost virtualHost, - final ServerSession session) - throws AMQException - { - String owner = body.getExclusive() ? session.getClientID() : null; - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()), queueName, body.getDurable(), owner, - body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments()); - - return queue; - } - - @Override - public void queueDelete(Session session, QueueDelete method) - { - String queueName = method.getQueue(); - if(queueName == null || queueName.length()==0) - { - exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "No queue name supplied"); - - } - else - { - AMQQueue queue = getQueue(session, queueName); - - - if (queue == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found"); - } - else - { - if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session) - { - exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); - } - else if(queue.isExclusive() && queue.getExclusiveOwningSession() != null && queue.getExclusiveOwningSession() != session) - { - exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session"); - } - else if (method.getIfEmpty() && !queue.isEmpty()) - { - exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " not empty"); - } - else if (method.getIfUnused() && !queue.isUnused()) - { - // TODO - Error code - exception(session, method, ExecutionErrorCode.PRECONDITION_FAILED, "Queue " + queueName + " in use"); - - } - else - { - VirtualHost virtualHost = getVirtualHost(session); - - try - { - queue.delete(); - if (queue.isDurable() && !queue.isAutoDelete()) - { - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - DurableConfigurationStoreHelper.removeQueue(store,queue); - } - } - catch (AMQException e) - { - exception(session, method, e, "Cannot delete queue '" + queueName); - } - } - } - } - } - - @Override - public void queuePurge(Session session, QueuePurge method) - { - String queueName = method.getQueue(); - if(queueName == null || queueName.length()==0) - { - exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "No queue name supplied"); - } - else - { - AMQQueue queue = getQueue(session, queueName); - - if (queue == null) - { - exception(session, method, ExecutionErrorCode.NOT_FOUND, "No queue " + queueName + " found"); - } - else - { - try - { - queue.clearQueue(); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot purge queue '" + queueName); - } - } - } - } - - @Override - public void queueQuery(Session session, QueueQuery method) - { - QueueQueryResult result = new QueueQueryResult(); - - AMQQueue queue = getQueue(session, method.getQueue()); - - if(queue != null) - { - result.setQueue(queue.getNameShortString().toString()); - result.setDurable(queue.isDurable()); - result.setExclusive(queue.isExclusive()); - result.setAutoDelete(queue.isAutoDelete()); - result.setArguments(queue.getArguments()); - result.setMessageCount(queue.getMessageCount()); - result.setSubscriberCount(queue.getConsumerCount()); - - } - - - session.executionResult((int) method.getId(), result); - - } - - @Override - public void messageSetFlowMode(Session session, MessageSetFlowMode sfm) - { - String destination = sfm.getDestination(); - - Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); - - if(sub == null) - { - exception(session, sfm, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); - } - else if(sub.isStopped()) - { - sub.setFlowMode(sfm.getFlowMode()); - } - } - - @Override - public void messageStop(Session session, MessageStop stop) - { - String destination = stop.getDestination(); - - Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); - - if(sub == null) - { - exception(session, stop, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); - } - else - { - sub.stop(); - } - - } - - @Override - public void messageFlow(Session session, MessageFlow flow) - { - String destination = flow.getDestination(); - - Subscription_0_10 sub = ((ServerSession)session).getSubscription(destination); - - if(sub == null) - { - exception(session, flow, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); - } - else - { - sub.addCredit(flow.getUnit(), flow.getValue()); - } - - } - - @Override - public void closed(Session session) - { - setThreadSubject(session); - - ServerSession serverSession = (ServerSession)session; - - serverSession.stopSubscriptions(); - serverSession.onClose(); - serverSession.unregisterSubscriptions(); - } - - @Override - public void detached(Session session) - { - closed(session); - } - - private void setThreadSubject(Session session) - { - final ServerConnection scon = (ServerConnection) session.getConnection(); - SecurityManager.setThreadSubject(scon.getAuthorizedSubject()); - } - - private static class CommandProcessedAction implements ServerTransaction.Action - { - private final ServerSession _serverSession; - private final Method _method; - - public CommandProcessedAction(final ServerSession serverSession, final Method xfr) - { - _serverSession = serverSession; - _method = xfr; - } - - public void postCommit() - { - _serverSession.processed(_method); - } - - public void onRollback() - { - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index 34c42cc9cc..1974584581 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -39,10 +39,10 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.LifetimePolicy; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java deleted file mode 100644 index e10bdbbb35..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java +++ /dev/null @@ -1,143 +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; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Map; - -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.abstraction.MessagePublishInfo; -import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.test.utils.QpidTestCase; - -public class AMQChannelTest extends QpidTestCase -{ - private VirtualHost _virtualHost; - private AMQProtocolSession _protocolSession; - private Map _replies; - private Broker _broker; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _virtualHost = BrokerTestHelper.createVirtualHost(getTestName()); - _broker = BrokerTestHelper.createBrokerMock(); - _protocolSession = new InternalTestProtocolSession(_virtualHost, _broker) - { - @Override - public void writeReturn(MessagePublishInfo messagePublishInfo, - ContentHeaderBody header, - MessageContentSource msgContent, - int channelId, - int replyCode, - AMQShortString replyText) throws AMQException - { - _replies.put(replyCode, replyText.asString()); - } - }; - _replies = new HashMap(); - } - - @Override - public void tearDown() throws Exception - { - try - { - _virtualHost.close(); - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - } - - public void testCompareTo() throws Exception - { - AMQChannel channel1 = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); - - // create a channel with the same channelId but on a different session - AMQChannel channel2 = new AMQChannel(new InternalTestProtocolSession(_virtualHost, _broker), 1, _virtualHost.getMessageStore()); - assertFalse("Unexpected compare result", channel1.compareTo(channel2) == 0); - assertEquals("Unexpected compare result", 0, channel1.compareTo(channel1)); - } - - public void testPublishContentHeaderWhenMessageAuthorizationFails() throws Exception - { - setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); - AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); - channel.setLocalTransactional(); - - MessagePublishInfo info = mock(MessagePublishInfo.class); - Exchange e = mock(Exchange.class); - ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); - BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); - - when(contentHeaderBody.getProperties()).thenReturn(properties); - when(info.getExchange()).thenReturn(new AMQShortString("test")); - when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName() + "_incorrect")); - - channel.setPublishFrame(info, e); - channel.publishContentHeader(contentHeaderBody); - channel.commit(); - - assertEquals("Unexpected number of replies", 1, _replies.size()); - assertEquals("Message authorization passed", "Access Refused", _replies.get(403)); - } - - public void testPublishContentHeaderWhenMessageAuthorizationPasses() throws Exception - { - setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); - AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); - channel.setLocalTransactional(); - - MessagePublishInfo info = mock(MessagePublishInfo.class); - Exchange e = mock(Exchange.class); - ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); - BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); - - when(contentHeaderBody.getProperties()).thenReturn(properties); - when(info.getExchange()).thenReturn(new AMQShortString("test")); - when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName())); - - channel.setPublishFrame(info, e); - channel.publishContentHeader(contentHeaderBody); - channel.commit(); - - assertEquals("Unexpected number of replies", 0, _replies.size()); - } - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java deleted file mode 100644 index 9756cdfd55..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java +++ /dev/null @@ -1,256 +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; - -import junit.framework.TestCase; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.MockAMQMessage; -import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.QueueEntryIterator; -import org.apache.qpid.server.queue.SimpleQueueEntryList; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TestMemoryMessageStore; -import org.apache.qpid.server.subscription.MockSubscription; -import org.apache.qpid.server.subscription.Subscription; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; - -/** - * QPID-1385 : Race condition between added to unacked map and resending due to a rollback. - * - * In AMQChannel _unackedMap.clear() was done after the visit. This meant that the clear was not in the same - * synchronized block as as the preparation to resend. - * - * This clearing/prep for resend was done as a result of the rollback call. HOWEVER, the delivery thread was still - * in the process of sending messages to the client. It is therefore possible that a message could block on the - * _unackedMap lock waiting for the visit to compelete so that it can add the new message to the unackedMap.... - * which is then cleared by the resend/rollback thread. - * - * This problem was encountered by the testSend2ThenRollback test. - * - * To try and increase the chance of the race condition occuring this test will send multiple messages so that the - * delivery thread will be in progress while the rollback method is called. Hopefully this will cause the - * deliveryTag to be lost - */ -public class ExtractResendAndRequeueTest extends TestCase -{ - - private UnacknowledgedMessageMapImpl _unacknowledgedMessageMap; - private static final int INITIAL_MSG_COUNT = 10; - private AMQQueue _queue = new MockAMQQueue(getName()); - private MessageStore _messageStore = new TestMemoryMessageStore(); - private LinkedList _referenceList = new LinkedList(); - - @Override - public void setUp() throws AMQException - { - _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(100); - - long id = 0; - SimpleQueueEntryList list = new SimpleQueueEntryList(_queue); - - // Add initial messages to QueueEntryList - for (int count = 0; count < INITIAL_MSG_COUNT; count++) - { - AMQMessage msg = new MockAMQMessage(id); - - list.add(msg); - - //Increment ID; - id++; - } - - // Iterate through the QueueEntryList and add entries to unacknowledgeMessageMap and referecenList - QueueEntryIterator queueEntries = list.iterator(); - while(queueEntries.advance()) - { - QueueEntry entry = queueEntries.getNode(); - _unacknowledgedMessageMap.add(entry.getMessage().getMessageNumber(), entry); - - // Store the entry for future inspection - _referenceList.add(entry); - } - - assertEquals("Map does not contain correct setup data", INITIAL_MSG_COUNT, _unacknowledgedMessageMap.size()); - } - - /** - * Helper method to create a new subscription and aquire the given messages. - * - * @param messageList The messages to aquire - * - * @return Subscription that performed the aquire - */ - private Subscription createSubscriptionAndAquireMessages(LinkedList messageList) - { - Subscription subscription = new MockSubscription(); - - // Aquire messages in subscription - for (QueueEntry entry : messageList) - { - entry.acquire(subscription); - } - - return subscription; - } - - /** - * This is the normal consumer rollback method. - * - * An active consumer that has aquired messages expects those messasges to be reset when rollback is requested. - * - * This test validates that the msgToResend map includes all the messages and none are left behind. - * - * @throws AMQException the visit interface throws this - */ - public void testResend() throws AMQException - { - //We don't need the subscription object here. - createSubscriptionAndAquireMessages(_referenceList); - - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - // requeueIfUnabletoResend doesn't matter here. - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, _messageStore)); - - assertEquals("Message count for resend not correct.", INITIAL_MSG_COUNT, msgToResend.size()); - assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); - assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); - } - - /** - * This is the normal consumer close method. - * - * When a consumer that has aquired messages expects closes the messages that it has aquired should be removed from - * the unacknowledgeMap and placed in msgToRequeue - * - * This test validates that the msgToRequeue map includes all the messages and none are left behind. - * - * @throws AMQException the visit interface throws this - */ - public void testRequeueDueToSubscriptionClosure() throws AMQException - { - Subscription subscription = createSubscriptionAndAquireMessages(_referenceList); - - // Close subscription - subscription.close(); - - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - // requeueIfUnabletoResend doesn't matter here. - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, _messageStore)); - - assertEquals("Message count for resend not correct.", 0, msgToResend.size()); - assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); - assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); - } - - /** - * If the subscription is null, due to message being retrieved via a GET, And we request that messages are requeued - * requeueIfUnabletoResend(set to true) then all messages should be sent to the msgToRequeue map. - * - * @throws AMQException the visit interface throws this - */ - - public void testRequeueDueToMessageHavingNoConsumerTag() throws AMQException - { - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - // requeueIfUnabletoResend = true so all messages should go to msgToRequeue - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, true, _messageStore)); - - assertEquals("Message count for resend not correct.", 0, msgToResend.size()); - assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); - assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); - } - - /** - * If the subscription is null, due to message being retrieved via a GET, And we request that we don't - * requeueIfUnabletoResend(set to false) then all messages should be dropped as we do not have a dead letter queue. - * - * @throws AMQException the visit interface throws this - */ - - public void testDrop() throws AMQException - { - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - // requeueIfUnabletoResend = false so all messages should be dropped all maps should be empty - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, false, _messageStore)); - - assertEquals("Message count for resend not correct.", 0, msgToResend.size()); - assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); - assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); - - - for (QueueEntry entry : _referenceList) - { - assertTrue("Message was not discarded", entry.isDeleted()); - } - - } - - /** - * If the subscription is null, due to message being retrieved via a GET, AND the queue upon which the message was - * delivered has been deleted then it is not possible to requeue. Currently we simply discar the message but in the - * future we may wish to dead letter the message. - * - * Validate that at the end of the visit all Maps are empty and all messages are marked as deleted - * - * @throws AMQException the visit interface throws this - */ - public void testDiscard() throws AMQException - { - final Map msgToRequeue = new LinkedHashMap(); - final Map msgToResend = new LinkedHashMap(); - - _queue.delete(); - - // requeueIfUnabletoResend : value doesn't matter here as queue has been deleted - _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, - msgToResend, false, _messageStore)); - - assertEquals("Message count for resend not correct.", 0, msgToResend.size()); - assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); - assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); - - for (QueueEntry entry : _referenceList) - { - assertTrue("Message was not discarded", entry.isDeleted()); - } - } - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java index 26fc51c400..0e4dbe87a3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java @@ -24,8 +24,8 @@ package org.apache.qpid.server.ack; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.InternalTestProtocolSession; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index 3ee2345cee..b2d7237737 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -28,8 +28,8 @@ import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java deleted file mode 100644 index bc651c9748..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java +++ /dev/null @@ -1,83 +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.flow; - -import org.apache.qpid.test.utils.QpidTestCase; - -public class WindowCreditManagerTest extends QpidTestCase -{ - private WindowCreditManager _creditManager; - - protected void setUp() throws Exception - { - super.setUp(); - _creditManager = new WindowCreditManager(); - } - - /** - * Tests that after the credit limit is cleared (e.g. from a message.stop command), credit is - * restored (e.g. from completed MessageTransfer) without increasing the available credit, and - * more credit is added, that the 'used' count is correct and the proper values for bytes - * and message credit are returned along with appropriate 'hasCredit' results (QPID-3592). - */ - public void testRestoreCreditDecrementsUsedCountAfterCreditClear() - { - assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); - assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); - - //give some message credit - _creditManager.addCredit(1, 0); - assertFalse("Manager should not 'haveCredit' due to having 0 bytes credit", _creditManager.hasCredit()); - assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); - assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); - - //give some bytes credit - _creditManager.addCredit(0, 1); - assertTrue("Manager should 'haveCredit'", _creditManager.hasCredit()); - assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); - assertEquals("unexpected credit value", 1, _creditManager.getBytesCredit()); - - //use all the credit - _creditManager.useCreditForMessage(1); - assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); - assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); - assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); - - //clear credit out (eg from a message.stop command) - _creditManager.clearCredit(); - assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); - assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); - assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); - - //restore credit (e.g the original message transfer command got completed) - //this should not increase credit, because it is now limited to 0 - _creditManager.restoreCredit(1, 1); - assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); - assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); - assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); - - //give more credit to open the window again - _creditManager.addCredit(1, 1); - assertEquals("unexpected credit value", 1, _creditManager.getBytesCredit()); - assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); - assertTrue("Manager should 'haveCredit'", _creditManager.hasCredit()); - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java index e2472dbf01..055197c23e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.util.BrokerTestHelper; import java.util.List; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java index 8ea5510ce6..0c64ce837e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java @@ -23,7 +23,7 @@ package org.apache.qpid.server.logging.actors; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.AMQException; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.NullRootMessageLogger; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java index d75e033739..a6701301f9 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; /** * Validate ChannelLogSubjects are logged as expected diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java index 7dc4c443ba..835bcb3e97 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.protocol.v0_8.InternalTestProtocolSession; import org.apache.qpid.server.util.BrokerTestHelper; /** diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java index 153d01f355..e314361a89 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java @@ -21,14 +21,14 @@ package org.apache.qpid.server.logging.subjects; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.flow.LimitlessCreditManager; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.protocol.v0_8.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; 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.v0_8.SubscriptionFactory; +import org.apache.qpid.server.protocol.v0_8.SubscriptionFactoryImpl; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -102,7 +102,7 @@ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject // MESSAGE [Blank][sub:0(vh(/ // test)/ // qu(SubscriptionLogSubjectTest))] - // Take the last bit and drop off the extra )] + // Take the last bit and drop off the extra )] String[] parts = message.split("/"); assertEquals("Message part count wrong", 3, parts.length); String subscription = parts[2].substring(0, parts[2].indexOf(")") + 1); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java index cd2a0959dc..b523979387 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java @@ -11,6 +11,7 @@ import org.apache.qpid.properties.ConnectionStartProperties; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolEngine; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.network.NetworkConnection; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java deleted file mode 100644 index 5d3051f7b2..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ /dev/null @@ -1,267 +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.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; -import org.apache.qpid.server.security.auth.UsernamePrincipal; -import org.apache.qpid.server.subscription.ClientDeliveryMethod; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionImpl; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.TestNetworkConnection; - -import javax.security.auth.Subject; - -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter -{ - // ChannelID(LIST) -> LinkedList - private final Map>> _channelDelivers; - private AtomicInteger _deliveryCount = new AtomicInteger(0); - private static final AtomicLong ID_GENERATOR = new AtomicLong(0); - - public InternalTestProtocolSession(VirtualHost virtualHost, Broker broker) throws AMQException - { - super(broker, new TestNetworkConnection(), ID_GENERATOR.getAndIncrement(), null, null); - - _channelDelivers = new HashMap>>(); - - setTestAuthorizedSubject(); - setVirtualHost(virtualHost); - } - - private void setTestAuthorizedSubject() - { - Principal principal = new AuthenticatedPrincipal(new UsernamePrincipal("InternalTestProtocolSession")); - Subject authorizedSubject = new Subject( - true, - Collections.singleton(principal), - Collections.emptySet(), - Collections.emptySet()); - - setAuthorizedSubject(authorizedSubject); - } - - public ProtocolOutputConverter getProtocolOutputConverter() - { - return this; - } - - public byte getProtocolMajorVersion() - { - return (byte) 8; - } - - public void writeReturn(MessagePublishInfo messagePublishInfo, - ContentHeaderBody header, - MessageContentSource msgContent, - int channelId, - int replyCode, - AMQShortString replyText) throws AMQException - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public byte getProtocolMinorVersion() - { - return (byte) 0; - } - - // *** - - public List getDelivers(int channelId, AMQShortString consumerTag, int count) - { - synchronized (_channelDelivers) - { - List all =_channelDelivers.get(channelId).get(consumerTag); - - if (all == null) - { - return new ArrayList(0); - } - - List msgs = all.subList(0, count); - - List response = new ArrayList(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 ClientDeliveryMethod createDeliveryMethod(int channelId) - { - return new InternalWriteDeliverMethod(channelId); - } - - public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) - { - } - - public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException - { - _deliveryCount.incrementAndGet(); - - synchronized (_channelDelivers) - { - Map> consumers = _channelDelivers.get(channelId); - - if (consumers == null) - { - consumers = new HashMap>(); - _channelDelivers.put(channelId, consumers); - } - - LinkedList consumerDelivers = consumers.get(consumerTag); - - if (consumerDelivers == null) - { - consumerDelivers = new LinkedList(); - consumers.put(consumerTag, consumerDelivers); - } - - consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage())); - } - } - - public void writeGetOk(QueueEntry 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 void closeProtocolSession() - { - // 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. - } - - public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException - { - super.closeSession(session, cause, message); - - //Simulate the Client responding with a CloseOK - // should really update the StateManger but we don't have access here - // changeState(AMQState.CONNECTION_CLOSED); - ((AMQChannel)session).getProtocolSession().closeSession(); - - } - - private class InternalWriteDeliverMethod implements ClientDeliveryMethod - { - private int _channelId; - - public InternalWriteDeliverMethod(int channelId) - { - _channelId = channelId; - } - - - public void deliverToClient(Subscription sub, QueueEntry entry, long deliveryTag) throws AMQException - { - _deliveryCount.incrementAndGet(); - - synchronized (_channelDelivers) - { - Map> consumers = _channelDelivers.get(_channelId); - - if (consumers == null) - { - consumers = new HashMap>(); - _channelDelivers.put(_channelId, consumers); - } - - LinkedList consumerDelivers = consumers.get(((SubscriptionImpl)sub).getConsumerTag()); - - if (consumerDelivers == null) - { - consumerDelivers = new LinkedList(); - consumers.put(((SubscriptionImpl)sub).getConsumerTag(), consumerDelivers); - } - - consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage())); - } - } - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java deleted file mode 100644 index 99dd42e179..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java +++ /dev/null @@ -1,84 +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.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; - -/** Test class to test MBean operations for AMQMinaProtocolSession. */ -public class MaxChannelsTest extends QpidTestCase -{ - private AMQProtocolEngine _session; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _session = BrokerTestHelper.createSession(); - } - - public void testChannels() throws Exception - { - // check the channel count is correct - int channelCount = _session.getChannels().size(); - assertEquals("Initial channel count wrong", 0, channelCount); - - long maxChannels = 10L; - _session.setMaximumNumberOfChannels(maxChannels); - assertEquals("Number of channels not correctly set.", new Long(maxChannels), _session.getMaximumNumberOfChannels()); - - for (long currentChannel = 0L; currentChannel < maxChannels; currentChannel++) - { - _session.addChannel(new AMQChannel(_session, (int) currentChannel, null)); - } - - try - { - _session.addChannel(new AMQChannel(_session, (int) maxChannels, null)); - fail("Cannot create more channels then maximum"); - } - catch (AMQException e) - { - assertEquals("Wrong exception recevied.", e.getErrorCode(), AMQConstant.NOT_ALLOWED); - } - assertEquals("Maximum number of channels not set.", new Long(maxChannels), new Long(_session.getChannels().size())); - } - - @Override - public void tearDown() throws Exception - { - try - { - _session.getVirtualHost().close(); - _session.closeSession(); - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - } - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java new file mode 100644 index 0000000000..7082705cb5 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java @@ -0,0 +1,80 @@ +/* + * 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.v0_10; + +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ServerSession; +import org.apache.qpid.server.protocol.v0_10.ServerSessionDelegate; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.Binary; + +public class ServerSessionTest extends QpidTestCase +{ + + private VirtualHost _virtualHost; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _virtualHost = BrokerTestHelper.createVirtualHost(getName()); + GenericActor.setDefaultMessageLogger(CurrentActor.get().getRootMessageLogger()); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_virtualHost != null) + { + _virtualHost.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + public void testCompareTo() throws Exception + { + ServerConnection connection = new ServerConnection(1); + connection.setVirtualHost(_virtualHost); + ServerSession session1 = new ServerSession(connection, new ServerSessionDelegate(), + new Binary(getName().getBytes()), 0); + + // create a session with the same name but on a different connection + ServerConnection connection2 = new ServerConnection(2); + connection2.setVirtualHost(_virtualHost); + ServerSession session2 = new ServerSession(connection2, new ServerSessionDelegate(), + new Binary(getName().getBytes()), 0); + + assertFalse("Unexpected compare result", session1.compareTo(session2) == 0); + assertEquals("Unexpected compare result", 0, session1.compareTo(session1)); + } + + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java new file mode 100644 index 0000000000..1c4a694be6 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.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.protocol.v0_10; + +import org.apache.qpid.server.protocol.v0_10.WindowCreditManager; +import org.apache.qpid.test.utils.QpidTestCase; + +public class WindowCreditManagerTest extends QpidTestCase +{ + private WindowCreditManager _creditManager; + + protected void setUp() throws Exception + { + super.setUp(); + _creditManager = new WindowCreditManager(); + } + + /** + * Tests that after the credit limit is cleared (e.g. from a message.stop command), credit is + * restored (e.g. from completed MessageTransfer) without increasing the available credit, and + * more credit is added, that the 'used' count is correct and the proper values for bytes + * and message credit are returned along with appropriate 'hasCredit' results (QPID-3592). + */ + public void testRestoreCreditDecrementsUsedCountAfterCreditClear() + { + assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); + assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); + + //give some message credit + _creditManager.addCredit(1, 0); + assertFalse("Manager should not 'haveCredit' due to having 0 bytes credit", _creditManager.hasCredit()); + assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); + assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); + + //give some bytes credit + _creditManager.addCredit(0, 1); + assertTrue("Manager should 'haveCredit'", _creditManager.hasCredit()); + assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); + assertEquals("unexpected credit value", 1, _creditManager.getBytesCredit()); + + //use all the credit + _creditManager.useCreditForMessage(1); + assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); + assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); + assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); + + //clear credit out (eg from a message.stop command) + _creditManager.clearCredit(); + assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); + assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); + assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); + + //restore credit (e.g the original message transfer command got completed) + //this should not increase credit, because it is now limited to 0 + _creditManager.restoreCredit(1, 1); + assertEquals("unexpected credit value", 0, _creditManager.getBytesCredit()); + assertEquals("unexpected credit value", 0, _creditManager.getMessageCredit()); + assertFalse("Manager should not 'haveCredit'", _creditManager.hasCredit()); + + //give more credit to open the window again + _creditManager.addCredit(1, 1); + assertEquals("unexpected credit value", 1, _creditManager.getBytesCredit()); + assertEquals("unexpected credit value", 1, _creditManager.getMessageCredit()); + assertTrue("Manager should 'haveCredit'", _creditManager.hasCredit()); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java new file mode 100644 index 0000000000..a5e5529ed5 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java @@ -0,0 +1,142 @@ +/* + * + * 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.v0_8; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +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.abstraction.MessagePublishInfo; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AMQChannelTest extends QpidTestCase +{ + private VirtualHost _virtualHost; + private AMQProtocolSession _protocolSession; + private Map _replies; + private Broker _broker; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _virtualHost = BrokerTestHelper.createVirtualHost(getTestName()); + _broker = BrokerTestHelper.createBrokerMock(); + _protocolSession = new InternalTestProtocolSession(_virtualHost, _broker) + { + @Override + public void writeReturn(MessagePublishInfo messagePublishInfo, + ContentHeaderBody header, + MessageContentSource msgContent, + int channelId, + int replyCode, + AMQShortString replyText) throws AMQException + { + _replies.put(replyCode, replyText.asString()); + } + }; + _replies = new HashMap(); + } + + @Override + public void tearDown() throws Exception + { + try + { + _virtualHost.close(); + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + public void testCompareTo() throws Exception + { + AMQChannel channel1 = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); + + // create a channel with the same channelId but on a different session + AMQChannel channel2 = new AMQChannel(new InternalTestProtocolSession(_virtualHost, _broker), 1, _virtualHost.getMessageStore()); + assertFalse("Unexpected compare result", channel1.compareTo(channel2) == 0); + assertEquals("Unexpected compare result", 0, channel1.compareTo(channel1)); + } + + public void testPublishContentHeaderWhenMessageAuthorizationFails() throws Exception + { + setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); + AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); + channel.setLocalTransactional(); + + MessagePublishInfo info = mock(MessagePublishInfo.class); + Exchange e = mock(Exchange.class); + ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); + BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); + + when(contentHeaderBody.getProperties()).thenReturn(properties); + when(info.getExchange()).thenReturn(new AMQShortString("test")); + when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName() + "_incorrect")); + + channel.setPublishFrame(info, e); + channel.publishContentHeader(contentHeaderBody); + channel.commit(); + + assertEquals("Unexpected number of replies", 1, _replies.size()); + assertEquals("Message authorization passed", "Access Refused", _replies.get(403)); + } + + public void testPublishContentHeaderWhenMessageAuthorizationPasses() throws Exception + { + setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); + AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); + channel.setLocalTransactional(); + + MessagePublishInfo info = mock(MessagePublishInfo.class); + Exchange e = mock(Exchange.class); + ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); + BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); + + when(contentHeaderBody.getProperties()).thenReturn(properties); + when(info.getExchange()).thenReturn(new AMQShortString("test")); + when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName())); + + channel.setPublishFrame(info, e); + channel.publishContentHeader(contentHeaderBody); + channel.commit(); + + assertEquals("Unexpected number of replies", 0, _replies.size()); + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java new file mode 100644 index 0000000000..60b6b215c6 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java @@ -0,0 +1,438 @@ +/* + * + * 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.v0_8; + + +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.abstraction.MessagePublishInfo; +import org.apache.qpid.server.flow.LimitlessCreditManager; +import org.apache.qpid.server.flow.Pre0_10CreditManager; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.IncomingMessage; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +import java.util.ArrayList; +import java.util.Set; + +/** + * Tests that acknowledgements are handled correctly. + */ +public class AckTest extends QpidTestCase +{ + private Subscription _subscription; + + private AMQProtocolSession _protocolSession; + + private TestableMemoryMessageStore _messageStore; + + private AMQChannel _channel; + + private AMQQueue _queue; + + private static final AMQShortString DEFAULT_CONSUMER_TAG = new AMQShortString("conTag"); + private VirtualHost _virtualHost; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _channel = BrokerTestHelper.createChannel(5); + _protocolSession = _channel.getProtocolSession(); + _virtualHost = _protocolSession.getVirtualHost(); + _queue = BrokerTestHelper.createQueue(getTestName(), _virtualHost); + _messageStore = (TestableMemoryMessageStore)_virtualHost.getMessageStore(); + } + + @Override + protected void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + + private void publishMessages(int count) throws AMQException + { + publishMessages(count, false); + } + + private void publishMessages(int count, boolean persistent) throws AMQException + { + _queue.registerSubscription(_subscription,false); + for (int i = 1; i <= count; i++) + { + // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) + // TODO: Establish some way to determine the version for the test. + MessagePublishInfo publishBody = new MessagePublishInfo() + { + + public AMQShortString getExchange() + { + return new AMQShortString("someExchange"); + } + + 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 new AMQShortString("rk"); + } + }; + final IncomingMessage msg = new IncomingMessage(publishBody); + //IncomingMessage msg2 = null; + BasicContentHeaderProperties b = new BasicContentHeaderProperties(); + ContentHeaderBody cb = new ContentHeaderBody(); + cb.setProperties(b); + + if (persistent) + { + //This is DeliveryMode.PERSISTENT + b.setDeliveryMode((byte) 2); + } + + msg.setContentHeaderBody(cb); + + // 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 + ArrayList qs = new ArrayList(); + qs.add(_queue); + msg.enqueue(qs); + MessageMetaData mmd = msg.headersReceived(System.currentTimeMillis()); + final StoredMessage storedMessage = _messageStore.addMessage(mmd); + msg.setStoredMessage(storedMessage); + final AMQMessage message = new AMQMessage(storedMessage); + if(msg.allContentReceived()) + { + ServerTransaction txn = new AutoCommitTransaction(_messageStore); + txn.enqueue(_queue, message, new ServerTransaction.Action() { + public void postCommit() + { + try + { + + _queue.enqueue(message); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + + public void onRollback() + { + //To change body of implemented methods use File | Settings | File Templates. + } + }); + + } + // we manually send the message to the subscription + //_subscription.send(new QueueEntry(_queue,msg), _queue); + } + try + { + Thread.sleep(2000L); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + + } + + /** + * Tests that the acknowledgements are correctly associated with a channel and + * order is preserved when acks are enabled + */ + public void testAckChannelAssociationTest() throws AMQException + { + _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(); + assertEquals("Unextpected size for unacknowledge message map",msgCount,map.size()); + + Set deliveryTagSet = map.getDeliveryTags(); + int i = 1; + for (long deliveryTag : deliveryTagSet) + { + assertTrue(deliveryTag == i); + i++; + QueueEntry unackedMsg = map.get(deliveryTag); + assertTrue(unackedMsg.getQueue() == _queue); + } + + } + + /** + * Tests that in no-ack mode no messages are retained + */ + public void testNoAckMode() 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); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertTrue(map.size() == 0); + assertTrue(_messageStore.getMessageCount() == 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.getMessageCount() == 0); + + + } + + /** + * Tests that a single acknowledgement is handled correctly (i.e multiple flag not + * set case) + */ + public void testSingleAckReceivedTest() throws AMQException + { + _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); + final int msgCount = 10; + publishMessages(msgCount); + + _channel.acknowledgeMessage(5, false); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertEquals("Map not expected size",msgCount - 1,map.size()); + + Set deliveryTagSet = map.getDeliveryTags(); + int i = 1; + for (long deliveryTag : deliveryTagSet) + { + assertTrue(deliveryTag == i); + QueueEntry unackedMsg = map.get(deliveryTag); + assertTrue(unackedMsg.getQueue() == _queue); + // 5 is the delivery tag of the message that *should* be removed + if (++i == 5) + { + ++i; + } + } + } + + /** + * Tests that a single acknowledgement is handled correctly (i.e multiple flag not + * set case) + */ + public void testMultiAckReceivedTest() throws AMQException + { + _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); + final int msgCount = 10; + publishMessages(msgCount); + + + + _channel.acknowledgeMessage(5, true); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertTrue(map.size() == 5); + + Set deliveryTagSet = map.getDeliveryTags(); + int i = 1; + for (long deliveryTag : deliveryTagSet) + { + assertTrue(deliveryTag == i + 5); + QueueEntry unackedMsg = map.get(deliveryTag); + assertTrue(unackedMsg.getQueue() == _queue); + ++i; + } + } + + /** + * Tests that a multiple acknowledgement is handled correctly. When ack'ing all pending msgs. + */ + public void testMultiAckAllReceivedTest() throws AMQException + { + _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); + final int msgCount = 10; + publishMessages(msgCount); + + _channel.acknowledgeMessage(0, true); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertTrue(map.size() == 0); + + Set deliveryTagSet = map.getDeliveryTags(); + int i = 1; + for (long deliveryTag : deliveryTagSet) + { + assertTrue(deliveryTag == i + 5); + 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 = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); + _channel.setPrefetchLowMarkCount(lowMark); + _channel.setPrefetchHighMarkCount(highMark); + + assertTrue(_channel.getPrefetchLowMarkCount() == lowMark); + assertTrue(_channel.getPrefetchHighMarkCount() == highMark); + + publishMessages(highMark); + + // at this point we should have sent out only highMark messages + // which have not bee received so will be queued up in the channel + // which should be suspended + assertTrue(_subscription.isSuspended()); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertTrue(map.size() == highMark); + + //acknowledge messages so we are just above lowMark + _channel.acknowledgeMessage(lowMark - 1, true); + + //we should still be suspended + assertTrue(_subscription.isSuspended()); + assertTrue(map.size() == lowMark + 1); + + //acknowledge one more message + _channel.acknowledgeMessage(lowMark, true); + + //and suspension should be lifted + assertTrue(!_subscription.isSuspended()); + + //pubilsh more msgs so we are just below the limit + publishMessages(lowMark - 1); + + //we should not be suspended + assertTrue(!_subscription.isSuspended()); + + //acknowledge all messages + _channel.acknowledgeMessage(0, true); + try + { + Thread.sleep(3000); + } + catch (InterruptedException e) + { + _log.error("Error: " + e, e); + } + //map will be empty + assertTrue(map.size() == 0); + } + +*/ +/* + public void testPrefetch() throws AMQException + { + _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); + _channel.setMessageCredit(5); + + assertTrue(_channel.getPrefetchCount() == 5); + + final int msgCount = 5; + publishMessages(msgCount); + + // at this point we should have sent out only 5 messages with a further 5 queued + // up in the channel which should now be suspended + assertTrue(_subscription.isSuspended()); + UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); + assertTrue(map.size() == 5); + _channel.acknowledgeMessage(5, true); + assertTrue(!_subscription.isSuspended()); + try + { + Thread.sleep(3000); + } + catch (InterruptedException e) + { + _log.error("Error: " + e, e); + } + assertTrue(map.size() == 0); + } + +*/ + public static junit.framework.Test suite() + { + return new junit.framework.TestSuite(AckTest.class); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java new file mode 100644 index 0000000000..2da93d2d99 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java @@ -0,0 +1,257 @@ +/* + * + * 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.v0_8; + +import junit.framework.TestCase; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.protocol.v0_8.UnacknowledgedMessageMapImpl; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.ExtractResendAndRequeue; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.MockAMQMessage; +import org.apache.qpid.server.queue.MockAMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.QueueEntryIterator; +import org.apache.qpid.server.queue.SimpleQueueEntryList; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.subscription.MockSubscription; +import org.apache.qpid.server.subscription.Subscription; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; + +/** + * QPID-1385 : Race condition between added to unacked map and resending due to a rollback. + * + * In AMQChannel _unackedMap.clear() was done after the visit. This meant that the clear was not in the same + * synchronized block as as the preparation to resend. + * + * This clearing/prep for resend was done as a result of the rollback call. HOWEVER, the delivery thread was still + * in the process of sending messages to the client. It is therefore possible that a message could block on the + * _unackedMap lock waiting for the visit to compelete so that it can add the new message to the unackedMap.... + * which is then cleared by the resend/rollback thread. + * + * This problem was encountered by the testSend2ThenRollback test. + * + * To try and increase the chance of the race condition occuring this test will send multiple messages so that the + * delivery thread will be in progress while the rollback method is called. Hopefully this will cause the + * deliveryTag to be lost + */ +public class ExtractResendAndRequeueTest extends TestCase +{ + + private UnacknowledgedMessageMapImpl _unacknowledgedMessageMap; + private static final int INITIAL_MSG_COUNT = 10; + private AMQQueue _queue = new MockAMQQueue(getName()); + private MessageStore _messageStore = new TestMemoryMessageStore(); + private LinkedList _referenceList = new LinkedList(); + + @Override + public void setUp() throws AMQException + { + _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(100); + + long id = 0; + SimpleQueueEntryList list = new SimpleQueueEntryList(_queue); + + // Add initial messages to QueueEntryList + for (int count = 0; count < INITIAL_MSG_COUNT; count++) + { + AMQMessage msg = new MockAMQMessage(id); + + list.add(msg); + + //Increment ID; + id++; + } + + // Iterate through the QueueEntryList and add entries to unacknowledgeMessageMap and referecenList + QueueEntryIterator queueEntries = list.iterator(); + while(queueEntries.advance()) + { + QueueEntry entry = queueEntries.getNode(); + _unacknowledgedMessageMap.add(entry.getMessage().getMessageNumber(), entry); + + // Store the entry for future inspection + _referenceList.add(entry); + } + + assertEquals("Map does not contain correct setup data", INITIAL_MSG_COUNT, _unacknowledgedMessageMap.size()); + } + + /** + * Helper method to create a new subscription and aquire the given messages. + * + * @param messageList The messages to aquire + * + * @return Subscription that performed the aquire + */ + private Subscription createSubscriptionAndAquireMessages(LinkedList messageList) + { + Subscription subscription = new MockSubscription(); + + // Aquire messages in subscription + for (QueueEntry entry : messageList) + { + entry.acquire(subscription); + } + + return subscription; + } + + /** + * This is the normal consumer rollback method. + * + * An active consumer that has aquired messages expects those messasges to be reset when rollback is requested. + * + * This test validates that the msgToResend map includes all the messages and none are left behind. + * + * @throws AMQException the visit interface throws this + */ + public void testResend() throws AMQException + { + //We don't need the subscription object here. + createSubscriptionAndAquireMessages(_referenceList); + + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + // requeueIfUnabletoResend doesn't matter here. + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, + msgToResend, true, _messageStore)); + + assertEquals("Message count for resend not correct.", INITIAL_MSG_COUNT, msgToResend.size()); + assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); + assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); + } + + /** + * This is the normal consumer close method. + * + * When a consumer that has aquired messages expects closes the messages that it has aquired should be removed from + * the unacknowledgeMap and placed in msgToRequeue + * + * This test validates that the msgToRequeue map includes all the messages and none are left behind. + * + * @throws AMQException the visit interface throws this + */ + public void testRequeueDueToSubscriptionClosure() throws AMQException + { + Subscription subscription = createSubscriptionAndAquireMessages(_referenceList); + + // Close subscription + subscription.close(); + + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + // requeueIfUnabletoResend doesn't matter here. + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, + msgToResend, true, _messageStore)); + + assertEquals("Message count for resend not correct.", 0, msgToResend.size()); + assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); + assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); + } + + /** + * If the subscription is null, due to message being retrieved via a GET, And we request that messages are requeued + * requeueIfUnabletoResend(set to true) then all messages should be sent to the msgToRequeue map. + * + * @throws AMQException the visit interface throws this + */ + + public void testRequeueDueToMessageHavingNoConsumerTag() throws AMQException + { + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + // requeueIfUnabletoResend = true so all messages should go to msgToRequeue + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, + msgToResend, true, _messageStore)); + + assertEquals("Message count for resend not correct.", 0, msgToResend.size()); + assertEquals("Message count for requeue not correct.", INITIAL_MSG_COUNT, msgToRequeue.size()); + assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); + } + + /** + * If the subscription is null, due to message being retrieved via a GET, And we request that we don't + * requeueIfUnabletoResend(set to false) then all messages should be dropped as we do not have a dead letter queue. + * + * @throws AMQException the visit interface throws this + */ + + public void testDrop() throws AMQException + { + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + // requeueIfUnabletoResend = false so all messages should be dropped all maps should be empty + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, + msgToResend, false, _messageStore)); + + assertEquals("Message count for resend not correct.", 0, msgToResend.size()); + assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); + assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); + + + for (QueueEntry entry : _referenceList) + { + assertTrue("Message was not discarded", entry.isDeleted()); + } + + } + + /** + * If the subscription is null, due to message being retrieved via a GET, AND the queue upon which the message was + * delivered has been deleted then it is not possible to requeue. Currently we simply discar the message but in the + * future we may wish to dead letter the message. + * + * Validate that at the end of the visit all Maps are empty and all messages are marked as deleted + * + * @throws AMQException the visit interface throws this + */ + public void testDiscard() throws AMQException + { + final Map msgToRequeue = new LinkedHashMap(); + final Map msgToResend = new LinkedHashMap(); + + _queue.delete(); + + // requeueIfUnabletoResend : value doesn't matter here as queue has been deleted + _unacknowledgedMessageMap.visit(new ExtractResendAndRequeue(_unacknowledgedMessageMap, msgToRequeue, + msgToResend, false, _messageStore)); + + assertEquals("Message count for resend not correct.", 0, msgToResend.size()); + assertEquals("Message count for requeue not correct.", 0, msgToRequeue.size()); + assertEquals("Map was not emptied", 0, _unacknowledgedMessageMap.size()); + + for (QueueEntry entry : _referenceList) + { + assertTrue("Message was not discarded", entry.isDeleted()); + } + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java new file mode 100644 index 0000000000..e8fda2bc65 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java @@ -0,0 +1,269 @@ +/* + * + * 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.v0_8; + +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.protocol.AMQConstant; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolEngine; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.protocol.v0_8.SubscriptionImpl; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.TestNetworkConnection; + +import javax.security.auth.Subject; + +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter +{ + // ChannelID(LIST) -> LinkedList + private final Map>> _channelDelivers; + private AtomicInteger _deliveryCount = new AtomicInteger(0); + private static final AtomicLong ID_GENERATOR = new AtomicLong(0); + + public InternalTestProtocolSession(VirtualHost virtualHost, Broker broker) throws AMQException + { + super(broker, new TestNetworkConnection(), ID_GENERATOR.getAndIncrement(), null, null); + + _channelDelivers = new HashMap>>(); + + setTestAuthorizedSubject(); + setVirtualHost(virtualHost); + } + + private void setTestAuthorizedSubject() + { + Principal principal = new AuthenticatedPrincipal(new UsernamePrincipal("InternalTestProtocolSession")); + Subject authorizedSubject = new Subject( + true, + Collections.singleton(principal), + Collections.emptySet(), + Collections.emptySet()); + + setAuthorizedSubject(authorizedSubject); + } + + public ProtocolOutputConverter getProtocolOutputConverter() + { + return this; + } + + public byte getProtocolMajorVersion() + { + return (byte) 8; + } + + public void writeReturn(MessagePublishInfo messagePublishInfo, + ContentHeaderBody header, + MessageContentSource msgContent, + int channelId, + int replyCode, + AMQShortString replyText) throws AMQException + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public byte getProtocolMinorVersion() + { + return (byte) 0; + } + + // *** + + public List getDelivers(int channelId, AMQShortString consumerTag, int count) + { + synchronized (_channelDelivers) + { + List all =_channelDelivers.get(channelId).get(consumerTag); + + if (all == null) + { + return new ArrayList(0); + } + + List msgs = all.subList(0, count); + + List response = new ArrayList(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 ClientDeliveryMethod createDeliveryMethod(int channelId) + { + return new InternalWriteDeliverMethod(channelId); + } + + public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag) + { + } + + public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException + { + _deliveryCount.incrementAndGet(); + + synchronized (_channelDelivers) + { + Map> consumers = _channelDelivers.get(channelId); + + if (consumers == null) + { + consumers = new HashMap>(); + _channelDelivers.put(channelId, consumers); + } + + LinkedList consumerDelivers = consumers.get(consumerTag); + + if (consumerDelivers == null) + { + consumerDelivers = new LinkedList(); + consumers.put(consumerTag, consumerDelivers); + } + + consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage())); + } + } + + public void writeGetOk(QueueEntry 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 void closeProtocolSession() + { + // 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. + } + + public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException + { + super.closeSession(session, cause, message); + + //Simulate the Client responding with a CloseOK + // should really update the StateManger but we don't have access here + // changeState(AMQState.CONNECTION_CLOSED); + ((AMQChannel)session).getProtocolSession().closeSession(); + + } + + private class InternalWriteDeliverMethod implements ClientDeliveryMethod + { + private int _channelId; + + public InternalWriteDeliverMethod(int channelId) + { + _channelId = channelId; + } + + + public void deliverToClient(Subscription sub, QueueEntry entry, long deliveryTag) throws AMQException + { + _deliveryCount.incrementAndGet(); + + synchronized (_channelDelivers) + { + Map> consumers = _channelDelivers.get(_channelId); + + if (consumers == null) + { + consumers = new HashMap>(); + _channelDelivers.put(_channelId, consumers); + } + + LinkedList consumerDelivers = consumers.get(((SubscriptionImpl)sub).getConsumerTag()); + + if (consumerDelivers == null) + { + consumerDelivers = new LinkedList(); + consumers.put(((SubscriptionImpl)sub).getConsumerTag(), consumerDelivers); + } + + consumerDelivers.add(new DeliveryPair(deliveryTag, (AMQMessage)entry.getMessage())); + } + } + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java new file mode 100644 index 0000000000..1cc872e177 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java @@ -0,0 +1,85 @@ +/* + * + * 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.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolEngine; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; + +/** Test class to test MBean operations for AMQMinaProtocolSession. */ +public class MaxChannelsTest extends QpidTestCase +{ + private AMQProtocolEngine _session; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _session = BrokerTestHelper.createSession(); + } + + public void testChannels() throws Exception + { + // check the channel count is correct + int channelCount = _session.getChannels().size(); + assertEquals("Initial channel count wrong", 0, channelCount); + + long maxChannels = 10L; + _session.setMaximumNumberOfChannels(maxChannels); + assertEquals("Number of channels not correctly set.", new Long(maxChannels), _session.getMaximumNumberOfChannels()); + + for (long currentChannel = 0L; currentChannel < maxChannels; currentChannel++) + { + _session.addChannel(new AMQChannel(_session, (int) currentChannel, null)); + } + + try + { + _session.addChannel(new AMQChannel(_session, (int) maxChannels, null)); + fail("Cannot create more channels then maximum"); + } + catch (AMQException e) + { + assertEquals("Wrong exception recevied.", e.getErrorCode(), AMQConstant.NOT_ALLOWED); + } + assertEquals("Maximum number of channels not set.", new Long(maxChannels), new Long(_session.getChannels().size())); + } + + @Override + public void tearDown() throws Exception + { + try + { + _session.getVirtualHost().close(); + _session.closeSession(); + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index 81ad57c040..25d4e4fa2c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java @@ -26,7 +26,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import java.util.ArrayList; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java deleted file mode 100644 index cbbf183232..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java +++ /dev/null @@ -1,440 +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.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.flow.LimitlessCreditManager; -import org.apache.qpid.server.flow.Pre0_10CreditManager; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.test.utils.QpidTestCase; - -import java.util.ArrayList; -import java.util.Set; - -/** - * Tests that acknowledgements are handled correctly. - */ -public class AckTest extends QpidTestCase -{ - private Subscription _subscription; - - private AMQProtocolSession _protocolSession; - - private TestableMemoryMessageStore _messageStore; - - private AMQChannel _channel; - - private AMQQueue _queue; - - private static final AMQShortString DEFAULT_CONSUMER_TAG = new AMQShortString("conTag"); - private VirtualHost _virtualHost; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _channel = BrokerTestHelper.createChannel(5); - _protocolSession = _channel.getProtocolSession(); - _virtualHost = _protocolSession.getVirtualHost(); - _queue = BrokerTestHelper.createQueue(getTestName(), _virtualHost); - _messageStore = (TestableMemoryMessageStore)_virtualHost.getMessageStore(); - } - - @Override - protected void tearDown() throws Exception - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - - private void publishMessages(int count) throws AMQException - { - publishMessages(count, false); - } - - private void publishMessages(int count, boolean persistent) throws AMQException - { - _queue.registerSubscription(_subscription,false); - for (int i = 1; i <= count; i++) - { - // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) - // TODO: Establish some way to determine the version for the test. - MessagePublishInfo publishBody = new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return new AMQShortString("someExchange"); - } - - 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 new AMQShortString("rk"); - } - }; - final IncomingMessage msg = new IncomingMessage(publishBody); - //IncomingMessage msg2 = null; - BasicContentHeaderProperties b = new BasicContentHeaderProperties(); - ContentHeaderBody cb = new ContentHeaderBody(); - cb.setProperties(b); - - if (persistent) - { - //This is DeliveryMode.PERSISTENT - b.setDeliveryMode((byte) 2); - } - - msg.setContentHeaderBody(cb); - - // 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 - ArrayList qs = new ArrayList(); - qs.add(_queue); - msg.enqueue(qs); - MessageMetaData mmd = msg.headersReceived(System.currentTimeMillis()); - final StoredMessage storedMessage = _messageStore.addMessage(mmd); - msg.setStoredMessage(storedMessage); - final AMQMessage message = new AMQMessage(storedMessage); - if(msg.allContentReceived()) - { - ServerTransaction txn = new AutoCommitTransaction(_messageStore); - txn.enqueue(_queue, message, new ServerTransaction.Action() { - public void postCommit() - { - try - { - - _queue.enqueue(message); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - } - - public void onRollback() - { - //To change body of implemented methods use File | Settings | File Templates. - } - }); - - } - // we manually send the message to the subscription - //_subscription.send(new QueueEntry(_queue,msg), _queue); - } - try - { - Thread.sleep(2000L); - } - catch (InterruptedException e) - { - Thread.currentThread().interrupt(); - } - - } - - /** - * Tests that the acknowledgements are correctly associated with a channel and - * order is preserved when acks are enabled - */ - public void testAckChannelAssociationTest() throws AMQException - { - _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(); - assertEquals("Unextpected size for unacknowledge message map",msgCount,map.size()); - - Set deliveryTagSet = map.getDeliveryTags(); - int i = 1; - for (long deliveryTag : deliveryTagSet) - { - assertTrue(deliveryTag == i); - i++; - QueueEntry unackedMsg = map.get(deliveryTag); - assertTrue(unackedMsg.getQueue() == _queue); - } - - } - - /** - * Tests that in no-ack mode no messages are retained - */ - public void testNoAckMode() 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); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == 0); - assertTrue(_messageStore.getMessageCount() == 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.getMessageCount() == 0); - - - } - - /** - * Tests that a single acknowledgement is handled correctly (i.e multiple flag not - * set case) - */ - public void testSingleAckReceivedTest() throws AMQException - { - _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); - final int msgCount = 10; - publishMessages(msgCount); - - _channel.acknowledgeMessage(5, false); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertEquals("Map not expected size",msgCount - 1,map.size()); - - Set deliveryTagSet = map.getDeliveryTags(); - int i = 1; - for (long deliveryTag : deliveryTagSet) - { - assertTrue(deliveryTag == i); - QueueEntry unackedMsg = map.get(deliveryTag); - assertTrue(unackedMsg.getQueue() == _queue); - // 5 is the delivery tag of the message that *should* be removed - if (++i == 5) - { - ++i; - } - } - } - - /** - * Tests that a single acknowledgement is handled correctly (i.e multiple flag not - * set case) - */ - public void testMultiAckReceivedTest() throws AMQException - { - _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); - final int msgCount = 10; - publishMessages(msgCount); - - - - _channel.acknowledgeMessage(5, true); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == 5); - - Set deliveryTagSet = map.getDeliveryTags(); - int i = 1; - for (long deliveryTag : deliveryTagSet) - { - assertTrue(deliveryTag == i + 5); - QueueEntry unackedMsg = map.get(deliveryTag); - assertTrue(unackedMsg.getQueue() == _queue); - ++i; - } - } - - /** - * Tests that a multiple acknowledgement is handled correctly. When ack'ing all pending msgs. - */ - public void testMultiAckAllReceivedTest() throws AMQException - { - _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); - final int msgCount = 10; - publishMessages(msgCount); - - _channel.acknowledgeMessage(0, true); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == 0); - - Set deliveryTagSet = map.getDeliveryTags(); - int i = 1; - for (long deliveryTag : deliveryTagSet) - { - assertTrue(deliveryTag == i + 5); - 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 = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); - _channel.setPrefetchLowMarkCount(lowMark); - _channel.setPrefetchHighMarkCount(highMark); - - assertTrue(_channel.getPrefetchLowMarkCount() == lowMark); - assertTrue(_channel.getPrefetchHighMarkCount() == highMark); - - publishMessages(highMark); - - // at this point we should have sent out only highMark messages - // which have not bee received so will be queued up in the channel - // which should be suspended - assertTrue(_subscription.isSuspended()); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == highMark); - - //acknowledge messages so we are just above lowMark - _channel.acknowledgeMessage(lowMark - 1, true); - - //we should still be suspended - assertTrue(_subscription.isSuspended()); - assertTrue(map.size() == lowMark + 1); - - //acknowledge one more message - _channel.acknowledgeMessage(lowMark, true); - - //and suspension should be lifted - assertTrue(!_subscription.isSuspended()); - - //pubilsh more msgs so we are just below the limit - publishMessages(lowMark - 1); - - //we should not be suspended - assertTrue(!_subscription.isSuspended()); - - //acknowledge all messages - _channel.acknowledgeMessage(0, true); - try - { - Thread.sleep(3000); - } - catch (InterruptedException e) - { - _log.error("Error: " + e, e); - } - //map will be empty - assertTrue(map.size() == 0); - } - -*/ -/* - public void testPrefetch() throws AMQException - { - _subscription = SubscriptionFactoryImpl.INSTANCE.createSubscription(5, _protocolSession, DEFAULT_CONSUMER_TAG, true,null,false, new LimitlessCreditManager()); - _channel.setMessageCredit(5); - - assertTrue(_channel.getPrefetchCount() == 5); - - final int msgCount = 5; - publishMessages(msgCount); - - // at this point we should have sent out only 5 messages with a further 5 queued - // up in the channel which should now be suspended - assertTrue(_subscription.isSuspended()); - UnacknowledgedMessageMap map = _channel.getUnacknowledgedMessageMap(); - assertTrue(map.size() == 5); - _channel.acknowledgeMessage(5, true); - assertTrue(!_subscription.isSuspended()); - try - { - Thread.sleep(3000); - } - catch (InterruptedException e) - { - _log.error("Error: " + e, e); - } - assertTrue(map.size() == 0); - } - -*/ - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(AckTest.class); - } -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java index a94548f1c3..d610ac08ed 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java @@ -23,10 +23,10 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import junit.framework.TestCase; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.AMQMessageHeader; -import org.apache.qpid.server.message.AMQMessageReference; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.AMQMessageReference; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java index 12369bd7d4..0e1c2d59de 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; public class MockAMQMessage extends AMQMessage { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java index 525093ccbd..6db00f4040 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java @@ -21,7 +21,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.subscription.Subscription; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java index 950d59bef5..6d1ad22a39 100755 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java @@ -24,7 +24,7 @@ import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.store.StoreFuture; import org.apache.qpid.server.store.StoredMessage; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java index 8be6061b45..8f61633d6a 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java @@ -21,7 +21,7 @@ package org.apache.qpid.server.queue; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.queue.QueueEntry.EntryState; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index c37e6da729..87f0c06c2b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -37,10 +37,9 @@ import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.DirectExchange; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.BaseQueue.PostEnqueueAction; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java index caf1eea09f..650a033dbc 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java @@ -21,9 +21,8 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.SimpleQueueEntryList.QueueEntryIteratorImpl; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -47,7 +46,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase assertNotNull("QE should not have been null", bleh); } } - + @Override protected void tearDown() { @@ -102,8 +101,8 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase { SimpleQueueEntryList sqel = new SimpleQueueEntryList(null); ConcurrentHashMap entriesMap = new ConcurrentHashMap(); - - + + //Add messages to generate QueueEntry's for(int i = 1; i <= 100 ; i++) { @@ -112,16 +111,16 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase assertNotNull("QE should not have been null", bleh); entriesMap.put(i,bleh); } - + SimpleQueueEntryImpl head = sqel.getHead(); - - //We shall now delete some specific messages mid-queue that will lead to + + //We shall now delete some specific messages mid-queue that will lead to //requiring a scavenge once the requested threshold of 9 deletes is passed - + //Delete the 2nd message only assertTrue("Failed to delete QueueEntry", entriesMap.remove(2).delete()); verifyDeletedButPresentBeforeScavenge(head, 2); - + //Delete messages 12 to 14 assertTrue("Failed to delete QueueEntry", entriesMap.remove(12).delete()); verifyDeletedButPresentBeforeScavenge(head, 12); @@ -147,7 +146,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase //Delete message 99 - this is the 10th message deleted that is after the queue head //and so will invoke the scavenge() which is set to go after 9 previous deletions assertTrue("Failed to delete QueueEntry", entriesMap.remove(99).delete()); - + verifyAllDeletedMessagedNotPresent(head, entriesMap); } @@ -173,9 +172,9 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase assertNotNull("Initial entry should not have been null", entry); int count = 0; - + while (entry != null) - { + { assertFalse("Entry " + entry.getMessage().getMessageNumber() + " should not have been deleted", entry.isDeleted()); assertNotNull("QueueEntry "+entry.getMessage().getMessageNumber()+" was not found in the list of remaining entries " + remainingMessages, remainingMessages.get((int)(entry.getMessage().getMessageNumber()))); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java index 38b12f8250..8e0d9522c7 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java @@ -20,7 +20,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.ServerMessage; import java.util.Arrays; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java index f57195b2d7..facc231bca 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java @@ -35,7 +35,7 @@ import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; import org.apache.qpid.server.message.EnqueableMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java index 7c6891da71..d50df47998 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java @@ -25,8 +25,8 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.test.utils.QpidTestCase; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java index 25b86eb73f..d9c0b7055f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java @@ -25,9 +25,8 @@ import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.store.MessageStore; @@ -130,7 +129,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase // indicate we are using the prefetch credit. i.e. using acks not No-Ack assertTrue("The subscription has been suspended", !getChannel().getSubscription(browser).getState() - .equals(Subscription.State.SUSPENDED)); + .equals(Subscription.State.SUSPENDED)); } private void checkStoreContents(int messageCount) diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java index efb62ba085..64521b64e2 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java @@ -23,15 +23,16 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.flow.WindowCreditManager; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_10.WindowCreditManager; import org.apache.qpid.server.logging.UnitTestMessageLogger; import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.ProtocolEngine_0_10; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.transport.ServerSessionDelegate; +import org.apache.qpid.server.protocol.v0_10.ProtocolEngine_0_10; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ServerSession; +import org.apache.qpid.server.protocol.v0_10.ServerSessionDelegate; +import org.apache.qpid.server.protocol.v0_8.SubscriptionFactoryImpl; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.Binary; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java deleted file mode 100644 index 3389773ff8..0000000000 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.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.transport; - -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.transport.Binary; - -public class ServerSessionTest extends QpidTestCase -{ - - private VirtualHost _virtualHost; - - @Override - public void setUp() throws Exception - { - super.setUp(); - BrokerTestHelper.setUp(); - _virtualHost = BrokerTestHelper.createVirtualHost(getName()); - GenericActor.setDefaultMessageLogger(CurrentActor.get().getRootMessageLogger()); - } - - @Override - public void tearDown() throws Exception - { - try - { - if (_virtualHost != null) - { - _virtualHost.close(); - } - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } - } - - public void testCompareTo() throws Exception - { - ServerConnection connection = new ServerConnection(1); - connection.setVirtualHost(_virtualHost); - ServerSession session1 = new ServerSession(connection, new ServerSessionDelegate(), - new Binary(getName().getBytes()), 0); - - // create a session with the same name but on a different connection - ServerConnection connection2 = new ServerConnection(2); - connection2.setVirtualHost(_virtualHost); - ServerSession session2 = new ServerSession(connection2, new ServerSessionDelegate(), - new Binary(getName().getBytes()), 0); - - assertFalse("Unexpected compare result", session1.compareTo(session2) == 0); - assertEquals("Unexpected compare result", 0, session1.compareTo(session1)); - } - - -} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 24cdf34360..bc4e67aefe 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -35,7 +35,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; import org.apache.qpid.server.exchange.DefaultExchangeFactory; @@ -48,7 +48,7 @@ import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.protocol.v0_8.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.security.SecurityManager; -- cgit v1.2.1