summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2008-04-24 17:49:03 +0000
committerRobert Godfrey <rgodfrey@apache.org>2008-04-24 17:49:03 +0000
commite32debe1df7d0a837e30cd937fb7a18fc5cfa203 (patch)
treeeda0dabab6fa1855d05df1ce8cab3f823f3e56ed
parent1a18bfd552d2065df2da734b42258249b01c4271 (diff)
downloadqpid-python-e32debe1df7d0a837e30cd937fb7a18fc5cfa203.tar.gz
QPID-832 : Fix eol-style
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@651325 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java480
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java130
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java202
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java150
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java242
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java1132
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java328
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java172
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java66
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java114
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java122
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java570
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java794
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java92
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java92
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java276
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java54
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java88
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java140
-rw-r--r--qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java686
-rw-r--r--qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java694
-rw-r--r--qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java550
-rw-r--r--qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java122
-rw-r--r--qpid/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java132
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQSessionAdapter.java52
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQUndefinedDestination.java80
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java132
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java76
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java150
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java98
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java270
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java72
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java1056
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java310
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java170
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java1604
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java1104
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQMethodNotImplementedException.java64
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/jms/Message.java56
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java208
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java442
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java288
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java178
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/AMQUnknownExchangeType.java86
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java192
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java60
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java180
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java1590
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java96
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java192
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/CommonContentHeaderProperties.java162
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java196
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java396
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/AbstractMethodConverter.java94
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java64
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfo.java76
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfoConverter.java64
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java64
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/AMQMethodBody_0_9.java418
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java344
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/AMQMethodBody_8_0.java418
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java302
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java114
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolVersionAware.java106
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java1378
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java390
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java150
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/PropertiesUtils.java400
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java456
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java88
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/AlreadyUnblockedException.java26
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueue.java202
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueueBase.java1626
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BooleanLatch.java214
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/Capacity.java28
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchBuffer.java58
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchException.java62
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchQueue.java54
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRecord.java106
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRef.java60
-rw-r--r--qpid/java/common/src/test/java/org/apache/qpid/util/CommandLineParserTest.java1108
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java270
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java418
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java478
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java428
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java486
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java168
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java180
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java176
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java386
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java386
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java1812
-rw-r--r--qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java252
-rw-r--r--qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java226
-rw-r--r--qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java548
-rw-r--r--qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java296
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java96
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java92
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java478
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java970
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java290
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java606
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java340
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java196
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java188
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java398
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java132
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java184
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java344
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java750
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java110
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java184
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java84
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java162
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java1250
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java1388
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java262
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java98
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java146
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java350
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java86
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java268
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java1064
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java528
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java264
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java800
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java1574
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java988
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java856
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java780
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java188
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java262
-rw-r--r--qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java404
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java214
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java904
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java622
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java186
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java392
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java906
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java3440
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java502
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java398
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java616
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java624
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java108
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java140
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java84
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java130
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java96
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java336
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java632
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java334
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java224
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java176
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java994
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java266
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java192
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java190
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java140
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java270
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/FailoverTest.java238
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java606
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java642
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java264
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java302
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java592
166 files changed, 32444 insertions, 32444 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
index e7c887f306..f1b383eac9 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java
@@ -1,240 +1,240 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.server.management.MBeanConstructor;
-import org.apache.qpid.server.management.MBeanDescription;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import java.util.List;
-import java.util.Map;
-import java.util.ArrayList;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-public class FanoutExchange extends AbstractExchange
-{
- private static final Logger _logger = Logger.getLogger(FanoutExchange.class);
-
- /**
- * Maps from queue name to queue instances
- */
- private final CopyOnWriteArraySet<AMQQueue> _queues = new CopyOnWriteArraySet<AMQQueue>();
-
- /**
- * MBean class implementing the management interfaces.
- */
- @MBeanDescription("Management Bean for Fanout Exchange")
- private final class FanoutExchangeMBean extends ExchangeMBean
- {
- @MBeanConstructor("Creates an MBean for AMQ fanout exchange")
- public FanoutExchangeMBean() throws JMException
- {
- super();
- _exchangeType = "fanout";
- init();
- }
-
- public TabularData bindings() throws OpenDataException
- {
-
- _bindingList = new TabularDataSupport(_bindinglistDataType);
-
- for (AMQQueue queue : _queues)
- {
- String queueName = queue.getName().toString();
-
- Object[] bindingItemValues = {queueName, new String[]{queueName}};
- CompositeData bindingData = new CompositeDataSupport(_bindingDataType, _bindingItemNames, bindingItemValues);
- _bindingList.put(bindingData);
- }
-
- return _bindingList;
- }
-
- public void createNewBinding(String queueName, String binding) throws JMException
- {
- AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName));
- if (queue == null)
- {
- throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange.");
- }
-
- try
- {
- queue.bind(new AMQShortString(binding), null, FanoutExchange.this);
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex);
- }
- }
-
- } // End of MBean class
-
- protected ExchangeMBean createMBean() throws AMQException
- {
- try
- {
- return new FanoutExchange.FanoutExchangeMBean();
- }
- catch (JMException ex)
- {
- _logger.error("Exception occured in creating the direct exchange mbean", ex);
- throw new AMQException("Exception occured in creating the direct exchange mbean", ex);
- }
- }
-
- public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
- {
-
- public AMQShortString getName()
- {
- return ExchangeDefaults.FANOUT_EXCHANGE_CLASS;
- }
-
- public Class<FanoutExchange> getExchangeClass()
- {
- return FanoutExchange.class;
- }
-
- public FanoutExchange newInstance(VirtualHost host,
- AMQShortString name,
- boolean durable,
- int ticket,
- boolean autoDelete) throws AMQException
- {
- FanoutExchange exch = new FanoutExchange();
- exch.initialise(host, name, durable, ticket, autoDelete);
- return exch;
- }
-
- public AMQShortString getDefaultExchangeName()
- {
- return ExchangeDefaults.FANOUT_EXCHANGE_NAME;
- }
- };
-
- public Map<AMQShortString, List<AMQQueue>> getBindings()
- {
- return null;
- }
-
- public AMQShortString getType()
- {
- return ExchangeDefaults.FANOUT_EXCHANGE_CLASS;
- }
-
- public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- assert queue != null;
-
- if (_queues.contains(queue))
- {
- _logger.debug("Queue " + queue + " is already registered");
- }
- else
- {
- _queues.add(queue);
- _logger.debug("Binding queue " + queue + " with routing key " + routingKey + " to exchange " + this);
- }
- }
-
- public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
- {
- assert queue != null;
-
- if (!_queues.remove(queue))
- {
- throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() + ". ");
- }
- }
-
- public void route(AMQMessage payload) throws AMQException
- {
- final MessagePublishInfo publishInfo = payload.getMessagePublishInfo();
- final AMQShortString routingKey = publishInfo.getRoutingKey();
- if ((_queues == null) || _queues.isEmpty())
- {
- String msg = "No queues bound to " + this;
- if (publishInfo.isMandatory() || publishInfo.isImmediate())
- {
- throw new NoRouteException(msg, payload);
- }
- else
- {
- _logger.warn(msg);
- }
- }
- else
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Publishing message to queue " + _queues);
- }
-
- payload.enqueue(new ArrayList(_queues));
-
- }
- }
-
- public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
- {
- return isBound(routingKey, queue);
- }
-
- public boolean isBound(AMQShortString routingKey, AMQQueue queue)
- {
- return _queues.contains(queue);
- }
-
- public boolean isBound(AMQShortString routingKey)
- {
-
- return (_queues != null) && !_queues.isEmpty();
- }
-
- public boolean isBound(AMQQueue queue)
- {
-
- return _queues.contains(queue);
- }
-
- public boolean hasBindings()
- {
- return !_queues.isEmpty();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.exchange;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.management.MBeanConstructor;
+import org.apache.qpid.server.management.MBeanDescription;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+import javax.management.JMException;
+import javax.management.MBeanException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class FanoutExchange extends AbstractExchange
+{
+ private static final Logger _logger = Logger.getLogger(FanoutExchange.class);
+
+ /**
+ * Maps from queue name to queue instances
+ */
+ private final CopyOnWriteArraySet<AMQQueue> _queues = new CopyOnWriteArraySet<AMQQueue>();
+
+ /**
+ * MBean class implementing the management interfaces.
+ */
+ @MBeanDescription("Management Bean for Fanout Exchange")
+ private final class FanoutExchangeMBean extends ExchangeMBean
+ {
+ @MBeanConstructor("Creates an MBean for AMQ fanout exchange")
+ public FanoutExchangeMBean() throws JMException
+ {
+ super();
+ _exchangeType = "fanout";
+ init();
+ }
+
+ public TabularData bindings() throws OpenDataException
+ {
+
+ _bindingList = new TabularDataSupport(_bindinglistDataType);
+
+ for (AMQQueue queue : _queues)
+ {
+ String queueName = queue.getName().toString();
+
+ Object[] bindingItemValues = {queueName, new String[]{queueName}};
+ CompositeData bindingData = new CompositeDataSupport(_bindingDataType, _bindingItemNames, bindingItemValues);
+ _bindingList.put(bindingData);
+ }
+
+ return _bindingList;
+ }
+
+ public void createNewBinding(String queueName, String binding) throws JMException
+ {
+ AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName));
+ if (queue == null)
+ {
+ throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange.");
+ }
+
+ try
+ {
+ queue.bind(new AMQShortString(binding), null, FanoutExchange.this);
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex);
+ }
+ }
+
+ } // End of MBean class
+
+ protected ExchangeMBean createMBean() throws AMQException
+ {
+ try
+ {
+ return new FanoutExchange.FanoutExchangeMBean();
+ }
+ catch (JMException ex)
+ {
+ _logger.error("Exception occured in creating the direct exchange mbean", ex);
+ throw new AMQException("Exception occured in creating the direct exchange mbean", ex);
+ }
+ }
+
+ public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>()
+ {
+
+ public AMQShortString getName()
+ {
+ return ExchangeDefaults.FANOUT_EXCHANGE_CLASS;
+ }
+
+ public Class<FanoutExchange> getExchangeClass()
+ {
+ return FanoutExchange.class;
+ }
+
+ public FanoutExchange newInstance(VirtualHost host,
+ AMQShortString name,
+ boolean durable,
+ int ticket,
+ boolean autoDelete) throws AMQException
+ {
+ FanoutExchange exch = new FanoutExchange();
+ exch.initialise(host, name, durable, ticket, autoDelete);
+ return exch;
+ }
+
+ public AMQShortString getDefaultExchangeName()
+ {
+ return ExchangeDefaults.FANOUT_EXCHANGE_NAME;
+ }
+ };
+
+ public Map<AMQShortString, List<AMQQueue>> getBindings()
+ {
+ return null;
+ }
+
+ public AMQShortString getType()
+ {
+ return ExchangeDefaults.FANOUT_EXCHANGE_CLASS;
+ }
+
+ public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ assert queue != null;
+
+ if (_queues.contains(queue))
+ {
+ _logger.debug("Queue " + queue + " is already registered");
+ }
+ else
+ {
+ _queues.add(queue);
+ _logger.debug("Binding queue " + queue + " with routing key " + routingKey + " to exchange " + this);
+ }
+ }
+
+ public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException
+ {
+ assert queue != null;
+
+ if (!_queues.remove(queue))
+ {
+ throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() + ". ");
+ }
+ }
+
+ public void route(AMQMessage payload) throws AMQException
+ {
+ final MessagePublishInfo publishInfo = payload.getMessagePublishInfo();
+ final AMQShortString routingKey = publishInfo.getRoutingKey();
+ if ((_queues == null) || _queues.isEmpty())
+ {
+ String msg = "No queues bound to " + this;
+ if (publishInfo.isMandatory() || publishInfo.isImmediate())
+ {
+ throw new NoRouteException(msg, payload);
+ }
+ else
+ {
+ _logger.warn(msg);
+ }
+ }
+ else
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Publishing message to queue " + _queues);
+ }
+
+ payload.enqueue(new ArrayList(_queues));
+
+ }
+ }
+
+ public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue)
+ {
+ return isBound(routingKey, queue);
+ }
+
+ public boolean isBound(AMQShortString routingKey, AMQQueue queue)
+ {
+ return _queues.contains(queue);
+ }
+
+ public boolean isBound(AMQShortString routingKey)
+ {
+
+ return (_queues != null) && !_queues.isEmpty();
+ }
+
+ public boolean isBound(AMQQueue queue)
+ {
+
+ return _queues.contains(queue);
+ }
+
+ public boolean hasBindings()
+ {
+ return !_queues.isEmpty();
+ }
+}
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
index dd712a404c..133c97a146 100644
--- 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
@@ -1,65 +1,65 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.AMQException;
-
-/**
- * @author Apache Software Foundation
- *
- *
- */
-public class AccessRequestHandler implements StateAwareMethodListener<AccessRequestBody>
-{
- private static final AccessRequestHandler _instance = new AccessRequestHandler();
-
-
- public static AccessRequestHandler getInstance()
- {
- return _instance;
- }
-
- private AccessRequestHandler()
- {
- }
-
- public void methodReceived(AMQStateManager stateManager, AccessRequestBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
- MethodRegistry methodRegistry = session.getMethodRegistry();
-
- // We don't implement access control class, but to keep clients happy that expect it
- // always use the "0" ticket.
- AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
-
- session.writeFrame(response.generateFrame(channelId));
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.AMQException;
+
+/**
+ * @author Apache Software Foundation
+ *
+ *
+ */
+public class AccessRequestHandler implements StateAwareMethodListener<AccessRequestBody>
+{
+ private static final AccessRequestHandler _instance = new AccessRequestHandler();
+
+
+ public static AccessRequestHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private AccessRequestHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, AccessRequestBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+
+ // We don't implement access control class, but to keep clients happy that expect it
+ // always use the "0" ticket.
+ AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
+
+ session.writeFrame(response.generateFrame(channelId));
+ }
+}
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
index f8f9127809..3731116cba 100644
--- 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
@@ -1,101 +1,101 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicGetBody;
-import org.apache.qpid.framing.BasicGetEmptyBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.Permission;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-
-public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody>
-{
- private static final Logger _log = Logger.getLogger(BasicGetMethodHandler.class);
-
- private static final BasicGetMethodHandler _instance = new BasicGetMethodHandler();
-
- public static BasicGetMethodHandler getInstance()
- {
- return _instance;
- }
-
- private BasicGetMethodHandler()
- {
- }
-
- public void methodReceived(AMQStateManager stateManager, BasicGetBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
-
- VirtualHost vHost = session.getVirtualHost();
-
- AMQChannel channel = session.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
- else
- {
- AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue());
-
- if (queue == null)
- {
- _log.info("No queue for '" + body.getQueue() + "'");
- if(body.getQueue()!=null)
- {
- throw body.getConnectionException(AMQConstant.NOT_FOUND,
- "No such queue, '" + body.getQueue()+ "'");
- }
- else
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "No queue name provided, no default queue defined.");
- }
- }
- else
- {
-
- //Perform ACLs
- vHost.getAccessManager().authorise(session, Permission.CONSUME, body, queue);
-
- if (!queue.performGet(session, channel, !body.getNoAck()))
- {
- MethodRegistry methodRegistry = session.getMethodRegistry();
- // TODO - set clusterId
- BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
-
-
- session.writeFrame(responseBody.generateFrame(channelId));
- }
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.BasicGetBody;
+import org.apache.qpid.framing.BasicGetEmptyBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.Permission;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+
+public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody>
+{
+ private static final Logger _log = Logger.getLogger(BasicGetMethodHandler.class);
+
+ private static final BasicGetMethodHandler _instance = new BasicGetMethodHandler();
+
+ public static BasicGetMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private BasicGetMethodHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, BasicGetBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+
+ VirtualHost vHost = session.getVirtualHost();
+
+ AMQChannel channel = session.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+ else
+ {
+ AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue());
+
+ if (queue == null)
+ {
+ _log.info("No queue for '" + body.getQueue() + "'");
+ if(body.getQueue()!=null)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_FOUND,
+ "No such queue, '" + body.getQueue()+ "'");
+ }
+ else
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "No queue name provided, no default queue defined.");
+ }
+ }
+ else
+ {
+
+ //Perform ACLs
+ vHost.getAccessManager().authorise(session, Permission.CONSUME, body, queue);
+
+ if (!queue.performGet(session, channel, !body.getNoAck()))
+ {
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ // TODO - set clusterId
+ BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
+
+
+ session.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }
+ }
+ }
+}
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
index 3e2cab2e53..bca35be535 100644
--- 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
@@ -1,75 +1,75 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.framing.BasicRecoverBody;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.framing.BasicRecoverSyncBody;
-import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
-import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.AMQException;
-
-public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<BasicRecoverSyncBody>
-{
- private static final Logger _logger = Logger.getLogger(BasicRecoverSyncMethodHandler.class);
-
- private static final BasicRecoverSyncMethodHandler _instance = new BasicRecoverSyncMethodHandler();
-
- public static BasicRecoverSyncMethodHandler getInstance()
- {
- return _instance;
- }
-
- public void methodReceived(AMQStateManager stateManager, BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
-
- _logger.debug("Recover received on protocol session " + session + " and channel " + channelId);
- AMQChannel channel = session.getChannel(channelId);
-
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
-
- channel.resend(body.getRequeue());
-
- // Qpid 0-8 hacks a synchronous -ok onto recover.
- // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
- if(session.getProtocolVersion().equals(ProtocolVersion.v0_9))
- {
- MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) session.getMethodRegistry();
- AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
- session.writeFrame(recoverOk.generateFrame(channelId));
-
- }
-
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.framing.BasicRecoverBody;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.BasicRecoverSyncBody;
+import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
+import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.AMQException;
+
+public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<BasicRecoverSyncBody>
+{
+ private static final Logger _logger = Logger.getLogger(BasicRecoverSyncMethodHandler.class);
+
+ private static final BasicRecoverSyncMethodHandler _instance = new BasicRecoverSyncMethodHandler();
+
+ public static BasicRecoverSyncMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ public void methodReceived(AMQStateManager stateManager, BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+
+ _logger.debug("Recover received on protocol session " + session + " and channel " + channelId);
+ AMQChannel channel = session.getChannel(channelId);
+
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+
+ channel.resend(body.getRequeue());
+
+ // Qpid 0-8 hacks a synchronous -ok onto recover.
+ // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
+ if(session.getProtocolVersion().equals(ProtocolVersion.v0_9))
+ {
+ MethodRegistry_0_9 methodRegistry = (MethodRegistry_0_9) session.getMethodRegistry();
+ AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+ session.writeFrame(recoverOk.generateFrame(channelId));
+
+ }
+
+ }
+}
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
index cce49f13c7..a854c97f60 100644
--- 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
@@ -1,121 +1,121 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.QueuePurgeBody;
-import org.apache.qpid.framing.QueuePurgeOkBody;
-import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQMethodEvent;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
-import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.access.Permission;
-
-public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
-{
- private static final QueuePurgeHandler _instance = new QueuePurgeHandler();
-
- public static QueuePurgeHandler getInstance()
- {
- return _instance;
- }
-
- private final boolean _failIfNotFound;
-
- public QueuePurgeHandler()
- {
- this(true);
- }
-
- public QueuePurgeHandler(boolean failIfNotFound)
- {
- _failIfNotFound = failIfNotFound;
- }
-
- public void methodReceived(AMQStateManager stateManager, QueuePurgeBody body, int channelId) throws AMQException
- {
- AMQProtocolSession session = stateManager.getProtocolSession();
- VirtualHost virtualHost = session.getVirtualHost();
- QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
-
- AMQChannel channel = session.getChannel(channelId);
-
-
- AMQQueue queue;
- if(body.getQueue() == null)
- {
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId);
- }
-
- //get the default queue on the channel:
- queue = channel.getDefaultQueue();
-
- if(queue == null)
- {
- if(_failIfNotFound)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,"No queue specified.");
- }
- }
- }
- else
- {
- queue = queueRegistry.getQueue(body.getQueue());
- }
-
- if(queue == null)
- {
- if(_failIfNotFound)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.");
- }
- }
- else
- {
-
- //Perform ACLs
- virtualHost.getAccessManager().authorise(session, Permission.PURGE, body, queue);
-
- long purged = queue.clearQueue(channel.getStoreContext());
-
-
- if(!body.getNowait())
- {
-
- MethodRegistry methodRegistry = session.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
- session.writeFrame(responseBody.generateFrame(channelId));
-
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.QueuePurgeBody;
+import org.apache.qpid.framing.QueuePurgeOkBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.protocol.AMQMethodEvent;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.security.access.Permission;
+
+public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody>
+{
+ private static final QueuePurgeHandler _instance = new QueuePurgeHandler();
+
+ public static QueuePurgeHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private final boolean _failIfNotFound;
+
+ public QueuePurgeHandler()
+ {
+ this(true);
+ }
+
+ public QueuePurgeHandler(boolean failIfNotFound)
+ {
+ _failIfNotFound = failIfNotFound;
+ }
+
+ public void methodReceived(AMQStateManager stateManager, QueuePurgeBody body, int channelId) throws AMQException
+ {
+ AMQProtocolSession session = stateManager.getProtocolSession();
+ VirtualHost virtualHost = session.getVirtualHost();
+ QueueRegistry queueRegistry = virtualHost.getQueueRegistry();
+
+ AMQChannel channel = session.getChannel(channelId);
+
+
+ AMQQueue queue;
+ if(body.getQueue() == null)
+ {
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId);
+ }
+
+ //get the default queue on the channel:
+ queue = channel.getDefaultQueue();
+
+ if(queue == null)
+ {
+ if(_failIfNotFound)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,"No queue specified.");
+ }
+ }
+ }
+ else
+ {
+ queue = queueRegistry.getQueue(body.getQueue());
+ }
+
+ if(queue == null)
+ {
+ if(_failIfNotFound)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.");
+ }
+ }
+ else
+ {
+
+ //Perform ACLs
+ virtualHost.getAccessManager().authorise(session, Permission.PURGE, body, queue);
+
+ long purged = queue.clearQueue(channel.getStoreContext());
+
+
+ if(!body.getNowait())
+ {
+
+ MethodRegistry methodRegistry = session.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
+ session.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ }
+ }
+}
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
index 9475b83c8f..d24e4f6ffa 100644
--- 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
@@ -1,566 +1,566 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.AMQException;
-
-public class ServerMethodDispatcherImpl implements MethodDispatcher
-{
- private final AMQStateManager _stateManager;
-
- private static interface DispatcherFactory
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager);
- }
-
- private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
- new HashMap<ProtocolVersion, DispatcherFactory>();
-
-
- static
- {
- _dispatcherFactories.put(ProtocolVersion.v8_0,
- new DispatcherFactory()
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ServerMethodDispatcherImpl_8_0(stateManager);
- }
- });
-
- _dispatcherFactories.put(ProtocolVersion.v0_9,
- new DispatcherFactory()
- {
- public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ServerMethodDispatcherImpl_0_9(stateManager);
- }
- });
-
- }
-
-
- private static final AccessRequestHandler _accessRequestHandler = AccessRequestHandler.getInstance();
- private static final ChannelCloseHandler _channelCloseHandler = ChannelCloseHandler.getInstance();
- private static final ChannelOpenHandler _channelOpenHandler = ChannelOpenHandler.getInstance();
- private static final ChannelCloseOkHandler _channelCloseOkHandler = ChannelCloseOkHandler.getInstance();
- private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
- private static final ConnectionCloseOkMethodHandler _connectionCloseOkMethodHandler = ConnectionCloseOkMethodHandler.getInstance();
- private static final ConnectionOpenMethodHandler _connectionOpenMethodHandler = ConnectionOpenMethodHandler.getInstance();
- private static final ConnectionTuneOkMethodHandler _connectionTuneOkMethodHandler = ConnectionTuneOkMethodHandler.getInstance();
- private static final ConnectionSecureOkMethodHandler _connectionSecureOkMethodHandler = ConnectionSecureOkMethodHandler.getInstance();
- private static final ConnectionStartOkMethodHandler _connectionStartOkMethodHandler = ConnectionStartOkMethodHandler.getInstance();
- private static final ExchangeDeclareHandler _exchangeDeclareHandler = ExchangeDeclareHandler.getInstance();
- private static final ExchangeDeleteHandler _exchangeDeleteHandler = ExchangeDeleteHandler.getInstance();
- private static final ExchangeBoundHandler _exchangeBoundHandler = ExchangeBoundHandler.getInstance();
- private static final BasicAckMethodHandler _basicAckMethodHandler = BasicAckMethodHandler.getInstance();
- private static final BasicRecoverMethodHandler _basicRecoverMethodHandler = BasicRecoverMethodHandler.getInstance();
- private static final BasicConsumeMethodHandler _basicConsumeMethodHandler = BasicConsumeMethodHandler.getInstance();
- private static final BasicGetMethodHandler _basicGetMethodHandler = BasicGetMethodHandler.getInstance();
- private static final BasicCancelMethodHandler _basicCancelMethodHandler = BasicCancelMethodHandler.getInstance();
- private static final BasicPublishMethodHandler _basicPublishMethodHandler = BasicPublishMethodHandler.getInstance();
- private static final BasicQosHandler _basicQosHandler = BasicQosHandler.getInstance();
- private static final QueueBindHandler _queueBindHandler = QueueBindHandler.getInstance();
- private static final QueueDeclareHandler _queueDeclareHandler = QueueDeclareHandler.getInstance();
- private static final QueueDeleteHandler _queueDeleteHandler = QueueDeleteHandler.getInstance();
- private static final QueuePurgeHandler _queuePurgeHandler = QueuePurgeHandler.getInstance();
- private static final ChannelFlowHandler _channelFlowHandler = ChannelFlowHandler.getInstance();
- private static final TxSelectHandler _txSelectHandler = TxSelectHandler.getInstance();
- private static final TxCommitHandler _txCommitHandler = TxCommitHandler.getInstance();
- private static final TxRollbackHandler _txRollbackHandler = TxRollbackHandler.getInstance();
- private static final BasicRejectMethodHandler _basicRejectMethodHandler = BasicRejectMethodHandler.getInstance();
-
-
-
- public static MethodDispatcher createMethodDispatcher(AMQStateManager stateManager, ProtocolVersion protocolVersion)
- {
- return _dispatcherFactories.get(protocolVersion).createMethodDispatcher(stateManager);
- }
-
-
- public ServerMethodDispatcherImpl(AMQStateManager stateManager)
- {
- _stateManager = stateManager;
- }
-
-
- protected AMQStateManager getStateManager()
- {
- return _stateManager;
- }
-
-
-
- public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
- {
- _accessRequestHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
- {
- _basicAckMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
- {
- _basicCancelMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
- {
- _basicConsumeMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
- {
- _basicGetMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
- {
- _basicPublishMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
- {
- _basicQosHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
- {
- _basicRecoverMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
- {
- _basicRejectMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
- {
- _channelOpenHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
- {
- _channelCloseHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
- {
- _channelCloseOkHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
- {
- _channelFlowHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
- {
- _connectionOpenMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
- {
- _connectionCloseMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
- public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
- {
- _connectionCloseOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
- {
- _connectionSecureOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
- {
- _connectionStartOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
- {
- _connectionTuneOkMethodHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
- {
- _exchangeBoundHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
- {
- _exchangeDeclareHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
- {
- _exchangeDeleteHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
- {
- _queueBindHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
- {
- _queueDeclareHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
- {
- _queueDeleteHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
- {
- _queuePurgeHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
- {
- _txCommitHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
- {
- _txRollbackHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
- public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
- {
- _txSelectHandler.methodReceived(_stateManager, body, channelId);
- return true;
- }
-
-
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.AMQException;
+
+public class ServerMethodDispatcherImpl implements MethodDispatcher
+{
+ private final AMQStateManager _stateManager;
+
+ private static interface DispatcherFactory
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager);
+ }
+
+ private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
+ new HashMap<ProtocolVersion, DispatcherFactory>();
+
+
+ static
+ {
+ _dispatcherFactories.put(ProtocolVersion.v8_0,
+ new DispatcherFactory()
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ServerMethodDispatcherImpl_8_0(stateManager);
+ }
+ });
+
+ _dispatcherFactories.put(ProtocolVersion.v0_9,
+ new DispatcherFactory()
+ {
+ public MethodDispatcher createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ServerMethodDispatcherImpl_0_9(stateManager);
+ }
+ });
+
+ }
+
+
+ private static final AccessRequestHandler _accessRequestHandler = AccessRequestHandler.getInstance();
+ private static final ChannelCloseHandler _channelCloseHandler = ChannelCloseHandler.getInstance();
+ private static final ChannelOpenHandler _channelOpenHandler = ChannelOpenHandler.getInstance();
+ private static final ChannelCloseOkHandler _channelCloseOkHandler = ChannelCloseOkHandler.getInstance();
+ private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
+ private static final ConnectionCloseOkMethodHandler _connectionCloseOkMethodHandler = ConnectionCloseOkMethodHandler.getInstance();
+ private static final ConnectionOpenMethodHandler _connectionOpenMethodHandler = ConnectionOpenMethodHandler.getInstance();
+ private static final ConnectionTuneOkMethodHandler _connectionTuneOkMethodHandler = ConnectionTuneOkMethodHandler.getInstance();
+ private static final ConnectionSecureOkMethodHandler _connectionSecureOkMethodHandler = ConnectionSecureOkMethodHandler.getInstance();
+ private static final ConnectionStartOkMethodHandler _connectionStartOkMethodHandler = ConnectionStartOkMethodHandler.getInstance();
+ private static final ExchangeDeclareHandler _exchangeDeclareHandler = ExchangeDeclareHandler.getInstance();
+ private static final ExchangeDeleteHandler _exchangeDeleteHandler = ExchangeDeleteHandler.getInstance();
+ private static final ExchangeBoundHandler _exchangeBoundHandler = ExchangeBoundHandler.getInstance();
+ private static final BasicAckMethodHandler _basicAckMethodHandler = BasicAckMethodHandler.getInstance();
+ private static final BasicRecoverMethodHandler _basicRecoverMethodHandler = BasicRecoverMethodHandler.getInstance();
+ private static final BasicConsumeMethodHandler _basicConsumeMethodHandler = BasicConsumeMethodHandler.getInstance();
+ private static final BasicGetMethodHandler _basicGetMethodHandler = BasicGetMethodHandler.getInstance();
+ private static final BasicCancelMethodHandler _basicCancelMethodHandler = BasicCancelMethodHandler.getInstance();
+ private static final BasicPublishMethodHandler _basicPublishMethodHandler = BasicPublishMethodHandler.getInstance();
+ private static final BasicQosHandler _basicQosHandler = BasicQosHandler.getInstance();
+ private static final QueueBindHandler _queueBindHandler = QueueBindHandler.getInstance();
+ private static final QueueDeclareHandler _queueDeclareHandler = QueueDeclareHandler.getInstance();
+ private static final QueueDeleteHandler _queueDeleteHandler = QueueDeleteHandler.getInstance();
+ private static final QueuePurgeHandler _queuePurgeHandler = QueuePurgeHandler.getInstance();
+ private static final ChannelFlowHandler _channelFlowHandler = ChannelFlowHandler.getInstance();
+ private static final TxSelectHandler _txSelectHandler = TxSelectHandler.getInstance();
+ private static final TxCommitHandler _txCommitHandler = TxCommitHandler.getInstance();
+ private static final TxRollbackHandler _txRollbackHandler = TxRollbackHandler.getInstance();
+ private static final BasicRejectMethodHandler _basicRejectMethodHandler = BasicRejectMethodHandler.getInstance();
+
+
+
+ public static MethodDispatcher createMethodDispatcher(AMQStateManager stateManager, ProtocolVersion protocolVersion)
+ {
+ return _dispatcherFactories.get(protocolVersion).createMethodDispatcher(stateManager);
+ }
+
+
+ public ServerMethodDispatcherImpl(AMQStateManager stateManager)
+ {
+ _stateManager = stateManager;
+ }
+
+
+ protected AMQStateManager getStateManager()
+ {
+ return _stateManager;
+ }
+
+
+
+ public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
+ {
+ _accessRequestHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
+ {
+ _basicAckMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
+ {
+ _basicCancelMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
+ {
+ _basicConsumeMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
+ {
+ _basicGetMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
+ {
+ _basicPublishMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
+ {
+ _basicQosHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
+ {
+ _basicRecoverMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
+ {
+ _basicRejectMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
+ {
+ _channelOpenHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
+ {
+ _channelCloseHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
+ {
+ _channelCloseOkHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
+ {
+ _channelFlowHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
+ {
+ _connectionOpenMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
+ {
+ _connectionCloseMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+ public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
+ {
+ _connectionCloseOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
+ {
+ _connectionSecureOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
+ {
+ _connectionStartOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
+ {
+ _connectionTuneOkMethodHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
+ {
+ _exchangeBoundHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
+ {
+ _exchangeDeclareHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
+ {
+ _exchangeDeleteHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
+ {
+ _queueBindHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
+ {
+ _queueDeclareHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
+ {
+ _queueDeleteHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
+ {
+ _queuePurgeHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
+ {
+ _txCommitHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
+ {
+ _txRollbackHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+ public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
+ {
+ _txSelectHandler.methodReceived(_stateManager, body, channelId);
+ return true;
+ }
+
+
+
+
+}
diff --git a/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
index 8b1dca77ba..382a85347b 100644
--- 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
@@ -1,164 +1,164 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-
-import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.AMQException;
-
-
-
-public class ServerMethodDispatcherImpl_0_9
- extends ServerMethodDispatcherImpl
- implements MethodDispatcher_0_9
-
-{
-
- private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler =
- BasicRecoverSyncMethodHandler.getInstance();
- private static final QueueUnbindHandler _queueUnbindHandler =
- QueueUnbindHandler.getInstance();
-
-
- public ServerMethodDispatcherImpl_0_9(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
- public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- _basicRecoverSyncMethodHandler.methodReceived(getStateManager(), body, channelId);
- return true;
- }
-
- public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelOk(ChannelOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelPing(ChannelPingBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelPong(ChannelPongBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelResume(ChannelResumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageCheckpoint(MessageCheckpointBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageClose(MessageCloseBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageConsume(MessageConsumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOffset(MessageOffsetBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOk(MessageOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageOpen(MessageOpenBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageQos(MessageQosBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageReject(MessageRejectBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageResume(MessageResumeBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageTransfer(MessageTransferBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
- {
- _queueUnbindHandler.methodReceived(getStateManager(),body,channelId);
- return true;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+
+import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.AMQException;
+
+
+
+public class ServerMethodDispatcherImpl_0_9
+ extends ServerMethodDispatcherImpl
+ implements MethodDispatcher_0_9
+
+{
+
+ private static final BasicRecoverSyncMethodHandler _basicRecoverSyncMethodHandler =
+ BasicRecoverSyncMethodHandler.getInstance();
+ private static final QueueUnbindHandler _queueUnbindHandler =
+ QueueUnbindHandler.getInstance();
+
+
+ public ServerMethodDispatcherImpl_0_9(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+ public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ _basicRecoverSyncMethodHandler.methodReceived(getStateManager(), body, channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelOk(ChannelOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelPing(ChannelPingBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelPong(ChannelPongBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelResume(ChannelResumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageCheckpoint(MessageCheckpointBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageClose(MessageCloseBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageConsume(MessageConsumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOffset(MessageOffsetBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOk(MessageOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageOpen(MessageOpenBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageQos(MessageQosBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageReject(MessageRejectBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageResume(MessageResumeBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageTransfer(MessageTransferBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
+ {
+ _queueUnbindHandler.methodReceived(getStateManager(),body,channelId);
+ return true;
+ }
+}
diff --git a/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
index d599ca3d4e..22f64cf7d3 100644
--- 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
@@ -1,86 +1,86 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.AMQException;
-
-public class ServerMethodDispatcherImpl_8_0
- extends ServerMethodDispatcherImpl
- implements MethodDispatcher_8_0
-{
- public ServerMethodDispatcherImpl_8_0(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
- public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTestContent(TestContentBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestContentOk(TestContentOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestInteger(TestIntegerBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestIntegerOk(TestIntegerOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestString(TestStringBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestStringOk(TestStringOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTable(TestTableBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTableOk(TestTableOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.AMQException;
+
+public class ServerMethodDispatcherImpl_8_0
+ extends ServerMethodDispatcherImpl
+ implements MethodDispatcher_8_0
+{
+ public ServerMethodDispatcherImpl_8_0(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+ public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTestContent(TestContentBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestContentOk(TestContentOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestInteger(TestIntegerBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestIntegerOk(TestIntegerOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestString(TestStringBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestStringOk(TestStringOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestTable(TestTableBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTestTableOk(TestTableOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+}
diff --git a/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
index fb18519fe1..0abb3cdd7d 100644
--- 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
@@ -1,33 +1,33 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.handler;
-
-
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.AMQException;
-
-public class UnexpectedMethodException extends AMQException
-{
- public UnexpectedMethodException(AMQMethodBody body)
- {
- super("Unexpected method recevied: " + body.getClass().getName());
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.handler;
+
+
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.AMQException;
+
+public class UnexpectedMethodException extends AMQException
+{
+ public UnexpectedMethodException(AMQMethodBody body)
+ {
+ super("Unexpected method recevied: " + body.getClass().getName());
+ }
+}
diff --git a/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
index e01c5aabbf..576d577b40 100644
--- 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
@@ -1,57 +1,57 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output;
-
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.AMQDataBlock;
-import org.apache.qpid.AMQException;
-
-public interface ProtocolOutputConverter
-{
- void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag);
-
- interface Factory
- {
- ProtocolOutputConverter newInstance(AMQProtocolSession session);
- }
-
- void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException;
-
- void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
-
- byte getProtocolMinorVersion();
-
- byte getProtocolMajorVersion();
-
- void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException;
-
- void writeFrame(AMQDataBlock block);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output;
+
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.AMQException;
+
+public interface ProtocolOutputConverter
+{
+ void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag);
+
+ interface Factory
+ {
+ ProtocolOutputConverter newInstance(AMQProtocolSession session);
+ }
+
+ void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException;
+
+ void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException;
+
+ byte getProtocolMinorVersion();
+
+ byte getProtocolMajorVersion();
+
+ void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException;
+
+ void writeFrame(AMQDataBlock block);
+}
diff --git a/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
index 36e7e88fd6..02fb1429c0 100644
--- 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
@@ -1,61 +1,61 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output;
-
-import org.apache.qpid.server.output.ProtocolOutputConverter.Factory;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.framing.ProtocolVersion;
-
-import java.util.Map;
-import java.util.HashMap;
-
-public class ProtocolOutputConverterRegistry
-{
-
- private static final Map<ProtocolVersion, Factory> _registry =
- new HashMap<ProtocolVersion, Factory>();
-
-
- static
- {
- register(ProtocolVersion.v8_0, org.apache.qpid.server.output.amqp0_8.ProtocolOutputConverterImpl.getInstanceFactory());
- register(ProtocolVersion.v0_9, org.apache.qpid.server.output.amqp0_9.ProtocolOutputConverterImpl.getInstanceFactory());
-
- }
-
- private static void register(ProtocolVersion version, Factory converter)
- {
-
- _registry.put(version,converter);
- }
-
-
- public static ProtocolOutputConverter getConverter(AMQProtocolSession session)
- {
- return _registry.get(session.getProtocolVersion()).newInstance(session);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output;
+
+import org.apache.qpid.server.output.ProtocolOutputConverter.Factory;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.framing.ProtocolVersion;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class ProtocolOutputConverterRegistry
+{
+
+ private static final Map<ProtocolVersion, Factory> _registry =
+ new HashMap<ProtocolVersion, Factory>();
+
+
+ static
+ {
+ register(ProtocolVersion.v8_0, org.apache.qpid.server.output.amqp0_8.ProtocolOutputConverterImpl.getInstanceFactory());
+ register(ProtocolVersion.v0_9, org.apache.qpid.server.output.amqp0_9.ProtocolOutputConverterImpl.getInstanceFactory());
+
+ }
+
+ private static void register(ProtocolVersion version, Factory converter)
+ {
+
+ _registry.put(version,converter);
+ }
+
+
+ public static ProtocolOutputConverter getConverter(AMQProtocolSession session)
+ {
+ return _registry.get(session.getProtocolVersion()).newInstance(session);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
index d7a879180a..d4cb7c878f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
@@ -1,285 +1,285 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*
- * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
- * Supported AMQP versions:
- * 8-0
- */
-package org.apache.qpid.server.output.amqp0_8;
-
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.AMQException;
-
-import org.apache.mina.common.ByteBuffer;
-
-import java.util.Iterator;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
-
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final Long messageId = message.getMessageId();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
-
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
-
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext,messageId, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final long messageId = message.getMessageId();
-
- AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
-
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, messageId, i);
- writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicDeliverBody deliverBody =
- methodRegistry.createBasicDeliverBody(consumerTag,
- deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey());
- AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
-
-
- return deliverFrame;
- }
-
- private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicGetOkBody getOkBody =
- methodRegistry.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
- queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
-
- return getOkFrame;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
- {
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicReturnBody basicReturnBody =
- methodRegistry.createBasicReturnBody(replyCode,
- replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
-
- return returnFrame;
- }
-
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- message.getContentHeaderBody());
-
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
- MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+/*
+ * This file is auto-generated by Qpid Gentools v.0.1 - do not modify.
+ * Supported AMQP versions:
+ * 8-0
+ */
+package org.apache.qpid.server.output.amqp0_8;
+
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.AMQException;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.util.Iterator;
+
+public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
+{
+
+
+ public static Factory getInstanceFactory()
+ {
+ return new Factory()
+ {
+
+ public ProtocolOutputConverter newInstance(AMQProtocolSession session)
+ {
+ return new ProtocolOutputConverterImpl(session);
+ }
+ };
+ }
+
+ private final AMQProtocolSession _protocolSession;
+
+ private ProtocolOutputConverterImpl(AMQProtocolSession session)
+ {
+ _protocolSession = session;
+ }
+
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _protocolSession;
+ }
+
+ public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ AMQDataBlock deliver = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+ final Long messageId = message.getMessageId();
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
+
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext,messageId, i);
+ writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+ final long messageId = message.getMessageId();
+
+ AMQDataBlock deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, messageId, i);
+ writeFrame(new AMQFrame(channelId, getProtocolSession().getMethodRegistry().getProtocolVersionMethodConverter().convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ private AMQDataBlock createEncodedDeliverFrame(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicDeliverBody deliverBody =
+ methodRegistry.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey());
+ AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
+
+
+ return deliverFrame;
+ }
+
+ private AMQDataBlock createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicGetOkBody getOkBody =
+ methodRegistry.createBasicGetOkBody(deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey(),
+ queueSize);
+ AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
+
+ return getOkFrame;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return getProtocolSession().getProtocolMinorVersion();
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return getProtocolSession().getProtocolMajorVersion();
+ }
+
+ private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ {
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicReturnBody basicReturnBody =
+ methodRegistry.createBasicReturnBody(replyCode,
+ replyText,
+ message.getMessagePublishInfo().getExchange(),
+ message.getMessagePublishInfo().getRoutingKey());
+ AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+
+ return returnFrame;
+ }
+
+ public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException
+ {
+ AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ message.getContentHeaderBody());
+
+ Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ if (bodyFrameIterator.hasNext())
+ {
+ AMQDataBlock firstContentBody = bodyFrameIterator.next();
+ AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
+
+ writeFrame(compositeBlock);
+ }
+
+ //
+ // Now start writing out the other content bodies
+ // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
+ //
+ while (bodyFrameIterator.hasNext())
+ {
+ writeFrame(bodyFrameIterator.next());
+ }
+ }
+
+
+ public void writeFrame(AMQDataBlock block)
+ {
+ getProtocolSession().writeFrame(block);
+ }
+
+
+ public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
+ {
+ MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
+ BasicCancelOkBody basicCancelOkBody = methodRegistry.createBasicCancelOkBody(consumerTag);
+ writeFrame(basicCancelOkBody.generateFrame(channelId));
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
index 48d2ca9bc9..f87d3bcae1 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
@@ -1,397 +1,397 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.output.amqp0_9;
-
-import org.apache.mina.common.ByteBuffer;
-
-import java.util.Iterator;
-
-import org.apache.qpid.server.output.ProtocolOutputConverter;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.queue.AMQMessageHandle;
-import org.apache.qpid.server.store.StoreContext;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-
-public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
-{
- private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
-
-
- public static Factory getInstanceFactory()
- {
- return new Factory()
- {
-
- public ProtocolOutputConverter newInstance(AMQProtocolSession session)
- {
- return new ProtocolOutputConverterImpl(session);
- }
- };
- }
-
- private final AMQProtocolSession _protocolSession;
-
- private ProtocolOutputConverterImpl(AMQProtocolSession session)
- {
- _protocolSession = session;
- }
-
-
- public AMQProtocolSession getProtocolSession()
- {
- return _protocolSession;
- }
-
- public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
- throws AMQException
- {
- AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
- final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
-
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final Long messageId = message.getMessageId();
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
-
- if(bodyCount == 0)
- {
- SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
- contentHeaderBody);
-
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
-
- CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext,messageId, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
- private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
- {
-
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
- contentHeaderBody);
- return contentHeader;
- }
-
-
- public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
- {
-
- final AMQMessageHandle messageHandle = message.getMessageHandle();
- final StoreContext storeContext = message.getStoreContext();
- final long messageId = message.getMessageId();
-
- AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
-
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
-
- final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
- if(bodyCount == 0)
- {
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
- writeFrame(compositeBlock);
- }
- else
- {
-
-
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
-
- AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
-
- //
- // Now start writing out the other content bodies
- //
- for(int i = 1; i < bodyCount; i++)
- {
- cb = messageHandle.getContentChunk(storeContext, messageId, i);
- writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
- }
-
-
- }
-
-
- }
-
-
- private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
- throws AMQException
- {
-
-
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
-
- final AMQBody returnBlock = new AMQBody()
- {
-
-
-
- private final boolean _isRedelivered = messageHandle.isRedelivered();
- private final AMQShortString _exchangeName = pb.getExchange();
- private final AMQShortString _routingKey = pb.getRoutingKey();
-
-
- public AMQBody _underlyingBody;
-
- public AMQBody createAMQBody()
- {
- return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- _isRedelivered,
- _exchangeName,
- _routingKey);
-
-
-
-
-
- }
-
- public byte getFrameType()
- {
- return AMQMethodBody.TYPE;
- }
-
- public int getSize()
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- return _underlyingBody.getSize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- if(_underlyingBody == null)
- {
- _underlyingBody = createAMQBody();
- }
- _underlyingBody.writePayload(buffer);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
- throws AMQException
- {
- throw new AMQException("This block should never be dispatched!");
- }
- };
- return returnBlock;
- }
-
- private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
- throws AMQException
- {
- final MessagePublishInfo pb = message.getMessagePublishInfo();
- final AMQMessageHandle messageHandle = message.getMessageHandle();
-
-
- BasicGetOkBody getOkBody =
- METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
- messageHandle.isRedelivered(),
- pb.getExchange(),
- pb.getRoutingKey(),
- queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
-
- return getOkFrame;
- }
-
- public byte getProtocolMinorVersion()
- {
- return getProtocolSession().getProtocolMinorVersion();
- }
-
- public byte getProtocolMajorVersion()
- {
- return getProtocolSession().getProtocolMajorVersion();
- }
-
- private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
- {
-
- BasicReturnBody basicReturnBody =
- METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- message.getMessagePublishInfo().getExchange(),
- message.getMessagePublishInfo().getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
-
- return returnFrame;
- }
-
- public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
- throws AMQException
- {
- AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
-
- AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
-
- Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
- //
- // Optimise the case where we have a single content body. In that case we create a composite block
- // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
- //
- if (bodyFrameIterator.hasNext())
- {
- AMQDataBlock firstContentBody = bodyFrameIterator.next();
- AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
- writeFrame(compositeBlock);
- }
- else
- {
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
-
- writeFrame(compositeBlock);
- }
-
- //
- // Now start writing out the other content bodies
- // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
- //
- while (bodyFrameIterator.hasNext())
- {
- writeFrame(bodyFrameIterator.next());
- }
- }
-
-
- public void writeFrame(AMQDataBlock block)
- {
- getProtocolSession().writeFrame(block);
- }
-
-
- public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
- {
-
- BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
- writeFrame(basicCancelOkBody.generateFrame(channelId));
-
- }
-
-
- public static final class CompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final AMQBody _contentBody;
- private final int _channel;
-
-
- public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
- _contentBody = contentBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
- }
- }
-
- public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
- {
- public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
-
- private final AMQBody _methodBody;
- private final AMQBody _headerBody;
- private final int _channel;
-
-
- public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
- {
- _channel = channel;
- _methodBody = methodBody;
- _headerBody = headerBody;
-
- }
-
- public long getSize()
- {
- return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
- }
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.output.amqp0_9;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.util.Iterator;
+
+import org.apache.qpid.server.output.ProtocolOutputConverter;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQMessageHandle;
+import org.apache.qpid.server.store.StoreContext;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+
+public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
+{
+ private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
+ private static final ProtocolVersionMethodConverter PROTOCOL_METHOD_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
+
+
+ public static Factory getInstanceFactory()
+ {
+ return new Factory()
+ {
+
+ public ProtocolOutputConverter newInstance(AMQProtocolSession session)
+ {
+ return new ProtocolOutputConverterImpl(session);
+ }
+ };
+ }
+
+ private final AMQProtocolSession _protocolSession;
+
+ private ProtocolOutputConverterImpl(AMQProtocolSession session)
+ {
+ _protocolSession = session;
+ }
+
+
+ public AMQProtocolSession getProtocolSession()
+ {
+ return _protocolSession;
+ }
+
+ public void writeDeliver(AMQMessage message, int channelId, long deliveryTag, AMQShortString consumerTag)
+ throws AMQException
+ {
+ AMQBody deliverBody = createEncodedDeliverFrame(message, channelId, deliveryTag, consumerTag);
+ final ContentHeaderBody contentHeaderBody = message.getContentHeaderBody();
+
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+ final Long messageId = message.getMessageId();
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
+
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
+ contentHeaderBody);
+
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
+
+ AMQBody firstContentBody = PROTOCOL_METHOD_CONVERTER.convertToBody(cb);
+
+ CompositeAMQBodyBlock compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext,messageId, i);
+ writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+ private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
+ {
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ contentHeaderBody);
+ return contentHeader;
+ }
+
+
+ public void writeGetOk(AMQMessage message, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+ final StoreContext storeContext = message.getStoreContext();
+ final long messageId = message.getMessageId();
+
+ AMQFrame deliver = createEncodedGetOkFrame(message, channelId, deliveryTag, queueSize);
+
+
+ AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+
+ final int bodyCount = messageHandle.getBodyCount(storeContext,messageId);
+ if(bodyCount == 0)
+ {
+ SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
+ contentHeader);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+
+
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ ContentChunk cb = messageHandle.getContentChunk(storeContext,messageId, 0);
+
+ AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb));
+ AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+
+ //
+ // Now start writing out the other content bodies
+ //
+ for(int i = 1; i < bodyCount; i++)
+ {
+ cb = messageHandle.getContentChunk(storeContext, messageId, i);
+ writeFrame(new AMQFrame(channelId, PROTOCOL_METHOD_CONVERTER.convertToBody(cb)));
+ }
+
+
+ }
+
+
+ }
+
+
+ private AMQBody createEncodedDeliverFrame(AMQMessage message, final int channelId, final long deliveryTag, final AMQShortString consumerTag)
+ throws AMQException
+ {
+
+
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+
+ final AMQBody returnBlock = new AMQBody()
+ {
+
+
+
+ private final boolean _isRedelivered = messageHandle.isRedelivered();
+ private final AMQShortString _exchangeName = pb.getExchange();
+ private final AMQShortString _routingKey = pb.getRoutingKey();
+
+
+ public AMQBody _underlyingBody;
+
+ public AMQBody createAMQBody()
+ {
+ return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ _isRedelivered,
+ _exchangeName,
+ _routingKey);
+
+
+
+
+
+ }
+
+ public byte getFrameType()
+ {
+ return AMQMethodBody.TYPE;
+ }
+
+ public int getSize()
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ return _underlyingBody.getSize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ _underlyingBody.writePayload(buffer);
+ }
+
+ public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
+ throws AMQException
+ {
+ throw new AMQException("This block should never be dispatched!");
+ }
+ };
+ return returnBlock;
+ }
+
+ private AMQFrame createEncodedGetOkFrame(AMQMessage message, int channelId, long deliveryTag, int queueSize)
+ throws AMQException
+ {
+ final MessagePublishInfo pb = message.getMessagePublishInfo();
+ final AMQMessageHandle messageHandle = message.getMessageHandle();
+
+
+ BasicGetOkBody getOkBody =
+ METHOD_REGISTRY.createBasicGetOkBody(deliveryTag,
+ messageHandle.isRedelivered(),
+ pb.getExchange(),
+ pb.getRoutingKey(),
+ queueSize);
+ AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
+
+ return getOkFrame;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return getProtocolSession().getProtocolMinorVersion();
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return getProtocolSession().getProtocolMajorVersion();
+ }
+
+ private AMQDataBlock createEncodedReturnFrame(AMQMessage message, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ {
+
+ BasicReturnBody basicReturnBody =
+ METHOD_REGISTRY.createBasicReturnBody(replyCode,
+ replyText,
+ message.getMessagePublishInfo().getExchange(),
+ message.getMessagePublishInfo().getRoutingKey());
+ AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+
+ return returnFrame;
+ }
+
+ public void writeReturn(AMQMessage message, int channelId, int replyCode, AMQShortString replyText)
+ throws AMQException
+ {
+ AMQDataBlock returnFrame = createEncodedReturnFrame(message, channelId, replyCode, replyText);
+
+ AMQDataBlock contentHeader = createContentHeaderBlock(channelId, message.getContentHeaderBody());
+
+ Iterator<AMQDataBlock> bodyFrameIterator = message.getBodyFrameIterator(getProtocolSession(), channelId);
+ //
+ // Optimise the case where we have a single content body. In that case we create a composite block
+ // so that we can writeDeliver out the deliver, header and body with a single network writeDeliver.
+ //
+ if (bodyFrameIterator.hasNext())
+ {
+ AMQDataBlock firstContentBody = bodyFrameIterator.next();
+ AMQDataBlock[] blocks = new AMQDataBlock[]{returnFrame, contentHeader, firstContentBody};
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ writeFrame(compositeBlock);
+ }
+ else
+ {
+ CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(new AMQDataBlock[]{returnFrame, contentHeader});
+
+ writeFrame(compositeBlock);
+ }
+
+ //
+ // Now start writing out the other content bodies
+ // TODO: MINA needs to be fixed so the the pending writes buffer is not unbounded
+ //
+ while (bodyFrameIterator.hasNext())
+ {
+ writeFrame(bodyFrameIterator.next());
+ }
+ }
+
+
+ public void writeFrame(AMQDataBlock block)
+ {
+ getProtocolSession().writeFrame(block);
+ }
+
+
+ public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
+ {
+
+ BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
+ writeFrame(basicCancelOkBody.generateFrame(channelId));
+
+ }
+
+
+ public static final class CompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final AMQBody _contentBody;
+ private final int _channel;
+
+
+ public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+ _contentBody = contentBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
+ }
+ }
+
+ public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final int _channel;
+
+
+ public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
+ }
+ }
+
+}
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
index a7599a3e0d..92f951ce39 100644
--- 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
@@ -1,46 +1,46 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.protocol.AMQMethodEvent;
-
-/**
- * AMQNoMethodHandlerException represents the case where no method handler exists to handle an AQMP method.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represents failure to handle an AMQP method.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Missing method handler. Unlikely to ever happen, and if it does its a coding error. Consider replacing with a
- * Runtime.
- */
-public class AMQNoMethodHandlerException extends AMQException
-{
- public AMQNoMethodHandlerException(AMQMethodEvent<AMQMethodBody> evt)
- {
- super("AMQMethodEvent " + evt + " was not processed by any listener on Broker.");
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.protocol.AMQMethodEvent;
+
+/**
+ * AMQNoMethodHandlerException represents the case where no method handler exists to handle an AQMP method.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents failure to handle an AMQP method.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Missing method handler. Unlikely to ever happen, and if it does its a coding error. Consider replacing with a
+ * Runtime.
+ */
+public class AMQNoMethodHandlerException extends AMQException
+{
+ public AMQNoMethodHandlerException(AMQMethodEvent<AMQMethodBody> evt)
+ {
+ super("AMQMethodEvent " + evt + " was not processed by any listener on Broker.");
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
index 6e72aa062f..bb2db8d506 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/UnknnownMessageTypeException.java
@@ -1,46 +1,46 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.protocol;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQDataBlock;
-
-/**
- * UnknnownMessageTypeException represents a failure when Mina passes an unexpected frame type.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represents failure to cast a frame to its expected type.
- * </table>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Seems like this exception was created to handle an unsafe type cast that will never happen in practice. Would
- * be better just to leave that as a ClassCastException. However, check the framing layer catches this error
- * first.
- */
-public class UnknnownMessageTypeException extends AMQException
-{
- public UnknnownMessageTypeException(AMQDataBlock message)
- {
- super("Unknown message type: " + message.getClass().getName() + ": " + message);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQDataBlock;
+
+/**
+ * UnknnownMessageTypeException represents a failure when Mina passes an unexpected frame type.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents failure to cast a frame to its expected type.
+ * </table>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Seems like this exception was created to handle an unsafe type cast that will never happen in practice. Would
+ * be better just to leave that as a ClassCastException. However, check the framing layer catches this error
+ * first.
+ */
+public class UnknnownMessageTypeException extends AMQException
+{
+ public UnknnownMessageTypeException(AMQDataBlock message)
+ {
+ super("Unknown message type: " + message.getClass().getName() + ": " + message);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
index 6f9efd3200..65115e4103 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java
@@ -1,138 +1,138 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-import org.apache.qpid.AMQException;
-
-public enum NotificationCheck
-{
-
- MESSAGE_COUNT_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- int msgCount;
- final long maximumMessageCount = queue.getMaximumMessageCount();
- if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
- {
- listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
- return true;
- }
- return false;
- }
- },
- MESSAGE_SIZE_ALERT(true)
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- final long maximumMessageSize = queue.getMaximumMessageSize();
- if(maximumMessageSize != 0)
- {
- // Check for threshold message size
- long messageSize;
- try
- {
- messageSize = (msg == null) ? 0 : msg.getContentHeaderBody().bodySize;
- }
- catch (AMQException e)
- {
- messageSize = 0;
- }
-
-
- if (messageSize >= maximumMessageSize)
- {
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageId() + "]");
- return true;
- }
- }
- return false;
- }
-
- },
- QUEUE_DEPTH_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
- // Check for threshold queue depth in bytes
- final long maximumQueueDepth = queue.getMaximumQueueDepth();
-
- if(maximumQueueDepth != 0)
- {
- final long queueDepth = queue.getQueueDepth();
-
- if (queueDepth >= maximumQueueDepth)
- {
- listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
- return true;
- }
- }
- return false;
- }
-
- },
- MESSAGE_AGE_ALERT
- {
- boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
- {
-
- final long maxMessageAge = queue.getMaximumMessageAge();
- if(maxMessageAge != 0)
- {
- final long currentTime = System.currentTimeMillis();
- final long thresholdTime = currentTime - maxMessageAge;
- final long firstArrivalTime = queue.getOldestMessageArrivalTime();
-
- if(firstArrivalTime < thresholdTime)
- {
- long oldestAge = currentTime - firstArrivalTime;
- listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
-
- return true;
- }
- }
- return false;
-
- }
-
- }
- ;
-
- private final boolean _messageSpecific;
-
- NotificationCheck()
- {
- this(false);
- }
-
- NotificationCheck(boolean messageSpecific)
- {
- _messageSpecific = messageSpecific;
- }
-
- public boolean isMessageSpecific()
- {
- return _messageSpecific;
- }
-
- abstract boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener);
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+import org.apache.qpid.AMQException;
+
+public enum NotificationCheck
+{
+
+ MESSAGE_COUNT_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ int msgCount;
+ final long maximumMessageCount = queue.getMaximumMessageCount();
+ if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
+ {
+ listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
+ return true;
+ }
+ return false;
+ }
+ },
+ MESSAGE_SIZE_ALERT(true)
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ final long maximumMessageSize = queue.getMaximumMessageSize();
+ if(maximumMessageSize != 0)
+ {
+ // Check for threshold message size
+ long messageSize;
+ try
+ {
+ messageSize = (msg == null) ? 0 : msg.getContentHeaderBody().bodySize;
+ }
+ catch (AMQException e)
+ {
+ messageSize = 0;
+ }
+
+
+ if (messageSize >= maximumMessageSize)
+ {
+ listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageId() + "]");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ },
+ QUEUE_DEPTH_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+ // Check for threshold queue depth in bytes
+ final long maximumQueueDepth = queue.getMaximumQueueDepth();
+
+ if(maximumQueueDepth != 0)
+ {
+ final long queueDepth = queue.getQueueDepth();
+
+ if (queueDepth >= maximumQueueDepth)
+ {
+ listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ },
+ MESSAGE_AGE_ALERT
+ {
+ boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ {
+
+ final long maxMessageAge = queue.getMaximumMessageAge();
+ if(maxMessageAge != 0)
+ {
+ final long currentTime = System.currentTimeMillis();
+ final long thresholdTime = currentTime - maxMessageAge;
+ final long firstArrivalTime = queue.getOldestMessageArrivalTime();
+
+ if(firstArrivalTime < thresholdTime)
+ {
+ long oldestAge = currentTime - firstArrivalTime;
+ listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
+
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ }
+ ;
+
+ private final boolean _messageSpecific;
+
+ NotificationCheck()
+ {
+ this(false);
+ }
+
+ NotificationCheck(boolean messageSpecific)
+ {
+ _messageSpecific = messageSpecific;
+ }
+
+ public boolean isMessageSpecific()
+ {
+ return _messageSpecific;
+ }
+
+ abstract boolean notifyIfNecessary(AMQMessage msg, AMQQueue queue, QueueNotificationListener listener);
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
index 959ca03c80..f1e7c98387 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java
@@ -1,27 +1,27 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.queue;
-
-
-public interface QueueNotificationListener
-{
- void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.queue;
+
+
+public interface QueueNotificationListener
+{
+ void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
index 85d804457e..70a76dd8c2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ManagedVirtualHost.java
@@ -1,44 +1,44 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.io.IOException;
-
-import org.apache.qpid.server.management.MBeanAttribute;
-
-/**
- * The management interface exposed to allow management of an Exchange.
- * @version 0.1
- */
-public interface ManagedVirtualHost
-{
- static final String TYPE = "VirtualHost";
-
- /**
- * Returns the name of the managed virtualHost.
- * @return the name of the exchange.
- * @throws java.io.IOException
- */
- @MBeanAttribute(name="Name", description= TYPE + " Name")
- String getName() throws IOException;
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.virtualhost;
+
+import java.io.IOException;
+
+import org.apache.qpid.server.management.MBeanAttribute;
+
+/**
+ * The management interface exposed to allow management of an Exchange.
+ * @version 0.1
+ */
+public interface ManagedVirtualHost
+{
+ static final String TYPE = "VirtualHost";
+
+ /**
+ * Returns the name of the managed virtualHost.
+ * @return the name of the exchange.
+ * @throws java.io.IOException
+ */
+ @MBeanAttribute(name="Name", description= TYPE + " Name")
+ String getName() throws IOException;
+
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
index 27917fac8a..9b1619c609 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java
@@ -1,70 +1,70 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.virtualhost;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-
-public class VirtualHostRegistry
-{
- private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
-
-
- private String _defaultVirtualHostName;
-
- public synchronized void registerVirtualHost(VirtualHost host) throws Exception
- {
- if(_registry.containsKey(host.getName()))
- {
- throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
- }
- _registry.put(host.getName(),host);
- }
-
- public VirtualHost getVirtualHost(String name)
- {
- if(name == null || name.trim().length() == 0 )
- {
- name = getDefaultVirtualHostName();
- }
-
- return _registry.get(name);
- }
-
- private String getDefaultVirtualHostName()
- {
- return _defaultVirtualHostName;
- }
-
- public void setDefaultVirtualHostName(String defaultVirtualHostName)
- {
- _defaultVirtualHostName = defaultVirtualHostName;
- }
-
-
- public Collection<VirtualHost> getVirtualHosts()
- {
- return new ArrayList<VirtualHost>(_registry.values());
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.virtualhost;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+public class VirtualHostRegistry
+{
+ private final Map<String, VirtualHost> _registry = new ConcurrentHashMap<String,VirtualHost>();
+
+
+ private String _defaultVirtualHostName;
+
+ public synchronized void registerVirtualHost(VirtualHost host) throws Exception
+ {
+ if(_registry.containsKey(host.getName()))
+ {
+ throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
+ }
+ _registry.put(host.getName(),host);
+ }
+
+ public VirtualHost getVirtualHost(String name)
+ {
+ if(name == null || name.trim().length() == 0 )
+ {
+ name = getDefaultVirtualHostName();
+ }
+
+ return _registry.get(name);
+ }
+
+ private String getDefaultVirtualHostName()
+ {
+ return _defaultVirtualHostName;
+ }
+
+ public void setDefaultVirtualHostName(String defaultVirtualHostName)
+ {
+ _defaultVirtualHostName = defaultVirtualHostName;
+ }
+
+
+ public Collection<VirtualHost> getVirtualHosts()
+ {
+ return new ArrayList<VirtualHost>(_registry.values());
+ }
+}
diff --git a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java
index 691020307a..ed8e4ad80f 100644
--- a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java
+++ b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/ClientFactoryImpl.java
@@ -1,343 +1,343 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sasl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.security.auth.callback.*;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslClientFactory;
-import javax.security.sasl.SaslException;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.util.PrettyPrintingUtils;
-
-/**
- * Implements a factory for generating Sasl client implementations.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a list of supported encryption mechansims that meet a defined set of Sasl properties.
- * <tr><td> Provide the best matching supported Sasl mechanism to a preference ordered list of mechanisms and Sasl
- * properties.
- * <tr><td> Perform username and password request call backs. <td> CallBackHandler
- * </table>
- */
-public class ClientFactoryImpl implements SaslClientFactory
-{
- //private static final Logger log = Logger.getLogger(ClientFactoryImpl.class);
-
- /** Holds the names of the supported encryption mechanisms. */
- private static final String[] SUPPORTED_MECHANISMS = { "CRAM-MD5", "PLAIN" };
-
- /** Defines index of the CRAM-MD5 mechanism within the supported mechanisms. */
- private static final int CRAM_MD5 = 0;
-
- /** Defines index of the PLAIN mechanism within the supported mechanisms. */
- private static final int PLAIN = 1;
-
- /** Bit mapping of the no plain text policy. */
- private static final int NOPLAINTEXT = 0x0001;
-
- /** Bit mapping of the no susceptible active attacks policy. */
- private static final int NOACTIVE = 0x0002;
-
- /** Bit mapping of the no susceptible to dictionary attacks policy. */
- private static final int NODICTIONARY = 0x0004;
-
- /** Bit mapping of the must use forward secrecy between sessions policy. */
- private static final int FORWARD_SECRECY = 0x0008;
-
- /** Bit mapping of the no anonymous logins policy. */
- private static final int NOANONYMOUS = 0x0010;
-
- /** Bit mapping of the must pass credentials policy. */
- private static final int PASS_CREDENTIALS = 0x0020;
-
- /** Defines a mapping from supported mechanisms to supported policy flags. */
- private static final int[] SUPPPORTED_MECHANISMS_POLICIES =
- {
- NOPLAINTEXT | NOANONYMOUS, // CRAM-MD5
- NOANONYMOUS // PLAIN
- };
-
- /**
- * Creates a SaslClient using the parameters supplied.
- *
- * @param mechanisms The non-null list of mechanism names to try. Each is the IANA-registered name of a SASL
- * mechanism. (e.g. "GSSAPI", "CRAM-MD5").
- * @param authorizationId The possibly null protocol-dependent identification to be used for authorization.
- * If null or empty, the server derives an authorization ID from the client's authentication
- * credentials. When the SASL authentication completes successfully, the specified entity is
- * granted access.
- * @param protocol The non-null string name of the protocol for which the authentication is being performed
- * (e.g., "ldap").
- * @param serverName The non-null fully qualified host name of the server to authenticate to.
- * @param props The possibly null set of properties used to select the SASL mechanism and to configure the
- * authentication exchange of the selected mechanism. See the <tt>Sasl</tt> class for a list
- * of standard properties. Other, possibly mechanism-specific, properties can be included.
- * Properties not relevant to the selected mechanism are ignored.
- * @param cbh The possibly null callback handler to used by the SASL mechanisms to get further
- * information from the application/library to complete the authentication. For example, a
- * SASL mechanism might require the authentication ID, password and realm from the caller.
- * The authentication ID is requested by using a <tt>NameCallback</tt>.
- * The password is requested by using a <tt>PasswordCallback</tt>.
- * The realm is requested by using a <tt>RealmChoiceCallback</tt> if there is a list
- * of realms to choose from, and by using a <tt>RealmCallback</tt> if
- * the realm must be entered.
- *
- * @return A possibly null <tt>SaslClient</tt> created using the parameters supplied. If null, this factory cannot
- * produce a <tt>SaslClient</tt> using the parameters supplied.
- *
- * @throws javax.security.sasl.SaslException If cannot create a <tt>SaslClient</tt> because of an error.
- */
- public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName,
- Map props, CallbackHandler cbh) throws SaslException
- {
- /*log.debug("public SaslClient createSaslClient(String[] mechanisms = " + PrettyPrintingUtils.printArray(mechanisms)
- + ", String authorizationId = " + authorizationId + ", String protocol = " + protocol
- + ", String serverName = " + serverName + ", Map props = " + props + ", CallbackHandler cbh): called");*/
-
- // Get a list of all supported mechanisms that matched the required properties.
- String[] matchingMechanisms = getMechanismNames(props);
- //log.debug("matchingMechanisms = " + PrettyPrintingUtils.printArray(matchingMechanisms));
-
- // Scan down the list of mechanisms until the first one that matches one of the matching supported mechanisms
- // is found.
- String chosenMechanism = null;
-
- for (int i = 0; i < mechanisms.length; i++)
- {
- String mechanism = mechanisms[i];
-
- for (int j = 0; j < matchingMechanisms.length; j++)
- {
- String matchingMechanism = matchingMechanisms[j];
-
- if (mechanism.equals(matchingMechanism))
- {
- chosenMechanism = mechanism;
-
- break;
- }
- }
-
- // Stop scanning if a match has been found.
- if (chosenMechanism != null)
- {
- break;
- }
- }
-
- // Check that a matching mechanism was found or return null otherwise.
- if (chosenMechanism == null)
- {
- //log.debug("No matching mechanism could be found.");
-
- return null;
- }
-
- // Instantiate an appropriate client type for the chosen mechanism.
- if (chosenMechanism.equals(SUPPORTED_MECHANISMS[CRAM_MD5]))
- {
- Object[] uinfo = getUserInfo("CRAM-MD5", authorizationId, cbh);
-
- //log.debug("Using CRAM-MD5 mechanism.");
-
- return new CramMD5Client((String) uinfo[0], (byte[]) uinfo[1]);
- }
- else
- {
- Object[] uinfo = getUserInfo("PLAIN", authorizationId, cbh);
-
- //log.debug("Using PLAIN mechanism.");
-
- return new PlainClient(authorizationId, (String) uinfo[0], (byte[]) uinfo[1]);
- }
- }
-
- /**
- * Returns an array of names of mechanisms that match the specified
- * mechanism selection policies.
- *
- * @param props The possibly null set of properties used to specify the
- * security policy of the SASL mechanisms. For example, if <tt>props</tt>
- * contains the <tt>Sasl.POLICY_NOPLAINTEXT</tt> property with the value
- * <tt>"true"</tt>, then the factory must not return any SASL mechanisms
- * that are susceptible to simple plain passive attacks.
- * See the <tt>Sasl</tt> class for a complete list of policy properties.
- * Non-policy related properties, if present in <tt>props</tt>, are ignored.
- *
- * @return A non-null array containing a IANA-registered SASL mechanism names.
- */
- public String[] getMechanismNames(Map props)
- {
- //log.debug("public String[] getMechanismNames(Map props = " + props + "): called");
-
- // Used to build up the valid mechanisms in.
- List validMechanisms = new ArrayList();
-
- // Transform the Sasl properties into a set of bit mapped flags indicating the required properties of the
- // encryption mechanism employed.
- int requiredFlags = bitMapSaslProperties(props);
- //log.debug("requiredFlags = " + requiredFlags);
-
- // Scan down the list of supported mechanisms filtering in only those that satisfy all of the desired
- // encryption properties.
- for (int i = 0; i < SUPPORTED_MECHANISMS.length; i++)
- {
- int mechanismFlags = SUPPPORTED_MECHANISMS_POLICIES[i];
- //log.debug("mechanismFlags = " + mechanismFlags);
-
- // Check if the current mechanism contains all of the required flags.
- if ((requiredFlags & ~mechanismFlags) == 0)
- {
- //log.debug("Mechanism " + SUPPORTED_MECHANISMS[i] + " meets the required properties.");
- validMechanisms.add(SUPPORTED_MECHANISMS[i]);
- }
- }
-
- String[] result = (String[]) validMechanisms.toArray(new String[validMechanisms.size()]);
-
- //log.debug("result = " + PrettyPrintingUtils.printArray(result));
-
- return result;
- }
-
- /**
- * Transforms a set of Sasl properties, defined using the property names in javax.security.sasl.Sasl, into
- * a bit mapped set of property flags encoded using the bit mapping constants defined in this class.
- *
- * @param properties The Sasl properties to bit map.
- *
- * @return A set of bit mapped properties encoded in an integer.
- */
- private int bitMapSaslProperties(Map properties)
- {
- //log.debug("private int bitMapSaslProperties(Map properties = " + properties + "): called");
-
- int result = 0;
-
- // No flags set if no properties are set.
- if (properties == null)
- {
- return result;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOPLAINTEXT)))
- {
- result |= NOPLAINTEXT;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOACTIVE)))
- {
- result |= NOACTIVE;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NODICTIONARY)))
- {
- result |= NODICTIONARY;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOANONYMOUS)))
- {
- result |= NOANONYMOUS;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_FORWARD_SECRECY)))
- {
- result |= FORWARD_SECRECY;
- }
-
- if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_PASS_CREDENTIALS)))
- {
- result |= PASS_CREDENTIALS;
- }
-
- return result;
- }
-
- /**
- * Uses the specified call back handler to query for the users log in name and password.
- *
- * @param prefix A prefix to prepend onto the username and password queries.
- * @param authorizationId The default autorhization name.
- * @param cbh The call back handler.
- *
- * @return The username and password from the callback.
- *
- * @throws SaslException If the callback fails for any reason.
- */
- private Object[] getUserInfo(String prefix, String authorizationId, CallbackHandler cbh) throws SaslException
- {
- // Check that the callback handler is defined.
- if (cbh == null)
- {
- throw new SaslException("Callback handler to get username/password required.");
- }
-
- try
- {
- String userPrompt = prefix + " authentication id: ";
- String passwdPrompt = prefix + " password: ";
-
- NameCallback ncb =
- (authorizationId == null) ? new NameCallback(userPrompt) : new NameCallback(userPrompt, authorizationId);
- PasswordCallback pcb = new PasswordCallback(passwdPrompt, false);
-
- // Ask the call back handler to get the users name and password.
- cbh.handle(new Callback[] { ncb, pcb });
-
- char[] pw = pcb.getPassword();
-
- byte[] bytepw;
- String authId;
-
- if (pw != null)
- {
- bytepw = new String(pw).getBytes("UTF8");
- pcb.clearPassword();
- }
- else
- {
- bytepw = null;
- }
-
- authId = ncb.getName();
-
- return new Object[] { authId, bytepw };
- }
- catch (IOException e)
- {
- throw new SaslException("Cannot get password.", e);
- }
- catch (UnsupportedCallbackException e)
- {
- throw new SaslException("Cannot get userid/password.", e);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.callback.*;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.util.PrettyPrintingUtils;
+
+/**
+ * Implements a factory for generating Sasl client implementations.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a list of supported encryption mechansims that meet a defined set of Sasl properties.
+ * <tr><td> Provide the best matching supported Sasl mechanism to a preference ordered list of mechanisms and Sasl
+ * properties.
+ * <tr><td> Perform username and password request call backs. <td> CallBackHandler
+ * </table>
+ */
+public class ClientFactoryImpl implements SaslClientFactory
+{
+ //private static final Logger log = Logger.getLogger(ClientFactoryImpl.class);
+
+ /** Holds the names of the supported encryption mechanisms. */
+ private static final String[] SUPPORTED_MECHANISMS = { "CRAM-MD5", "PLAIN" };
+
+ /** Defines index of the CRAM-MD5 mechanism within the supported mechanisms. */
+ private static final int CRAM_MD5 = 0;
+
+ /** Defines index of the PLAIN mechanism within the supported mechanisms. */
+ private static final int PLAIN = 1;
+
+ /** Bit mapping of the no plain text policy. */
+ private static final int NOPLAINTEXT = 0x0001;
+
+ /** Bit mapping of the no susceptible active attacks policy. */
+ private static final int NOACTIVE = 0x0002;
+
+ /** Bit mapping of the no susceptible to dictionary attacks policy. */
+ private static final int NODICTIONARY = 0x0004;
+
+ /** Bit mapping of the must use forward secrecy between sessions policy. */
+ private static final int FORWARD_SECRECY = 0x0008;
+
+ /** Bit mapping of the no anonymous logins policy. */
+ private static final int NOANONYMOUS = 0x0010;
+
+ /** Bit mapping of the must pass credentials policy. */
+ private static final int PASS_CREDENTIALS = 0x0020;
+
+ /** Defines a mapping from supported mechanisms to supported policy flags. */
+ private static final int[] SUPPPORTED_MECHANISMS_POLICIES =
+ {
+ NOPLAINTEXT | NOANONYMOUS, // CRAM-MD5
+ NOANONYMOUS // PLAIN
+ };
+
+ /**
+ * Creates a SaslClient using the parameters supplied.
+ *
+ * @param mechanisms The non-null list of mechanism names to try. Each is the IANA-registered name of a SASL
+ * mechanism. (e.g. "GSSAPI", "CRAM-MD5").
+ * @param authorizationId The possibly null protocol-dependent identification to be used for authorization.
+ * If null or empty, the server derives an authorization ID from the client's authentication
+ * credentials. When the SASL authentication completes successfully, the specified entity is
+ * granted access.
+ * @param protocol The non-null string name of the protocol for which the authentication is being performed
+ * (e.g., "ldap").
+ * @param serverName The non-null fully qualified host name of the server to authenticate to.
+ * @param props The possibly null set of properties used to select the SASL mechanism and to configure the
+ * authentication exchange of the selected mechanism. See the <tt>Sasl</tt> class for a list
+ * of standard properties. Other, possibly mechanism-specific, properties can be included.
+ * Properties not relevant to the selected mechanism are ignored.
+ * @param cbh The possibly null callback handler to used by the SASL mechanisms to get further
+ * information from the application/library to complete the authentication. For example, a
+ * SASL mechanism might require the authentication ID, password and realm from the caller.
+ * The authentication ID is requested by using a <tt>NameCallback</tt>.
+ * The password is requested by using a <tt>PasswordCallback</tt>.
+ * The realm is requested by using a <tt>RealmChoiceCallback</tt> if there is a list
+ * of realms to choose from, and by using a <tt>RealmCallback</tt> if
+ * the realm must be entered.
+ *
+ * @return A possibly null <tt>SaslClient</tt> created using the parameters supplied. If null, this factory cannot
+ * produce a <tt>SaslClient</tt> using the parameters supplied.
+ *
+ * @throws javax.security.sasl.SaslException If cannot create a <tt>SaslClient</tt> because of an error.
+ */
+ public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName,
+ Map props, CallbackHandler cbh) throws SaslException
+ {
+ /*log.debug("public SaslClient createSaslClient(String[] mechanisms = " + PrettyPrintingUtils.printArray(mechanisms)
+ + ", String authorizationId = " + authorizationId + ", String protocol = " + protocol
+ + ", String serverName = " + serverName + ", Map props = " + props + ", CallbackHandler cbh): called");*/
+
+ // Get a list of all supported mechanisms that matched the required properties.
+ String[] matchingMechanisms = getMechanismNames(props);
+ //log.debug("matchingMechanisms = " + PrettyPrintingUtils.printArray(matchingMechanisms));
+
+ // Scan down the list of mechanisms until the first one that matches one of the matching supported mechanisms
+ // is found.
+ String chosenMechanism = null;
+
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ String mechanism = mechanisms[i];
+
+ for (int j = 0; j < matchingMechanisms.length; j++)
+ {
+ String matchingMechanism = matchingMechanisms[j];
+
+ if (mechanism.equals(matchingMechanism))
+ {
+ chosenMechanism = mechanism;
+
+ break;
+ }
+ }
+
+ // Stop scanning if a match has been found.
+ if (chosenMechanism != null)
+ {
+ break;
+ }
+ }
+
+ // Check that a matching mechanism was found or return null otherwise.
+ if (chosenMechanism == null)
+ {
+ //log.debug("No matching mechanism could be found.");
+
+ return null;
+ }
+
+ // Instantiate an appropriate client type for the chosen mechanism.
+ if (chosenMechanism.equals(SUPPORTED_MECHANISMS[CRAM_MD5]))
+ {
+ Object[] uinfo = getUserInfo("CRAM-MD5", authorizationId, cbh);
+
+ //log.debug("Using CRAM-MD5 mechanism.");
+
+ return new CramMD5Client((String) uinfo[0], (byte[]) uinfo[1]);
+ }
+ else
+ {
+ Object[] uinfo = getUserInfo("PLAIN", authorizationId, cbh);
+
+ //log.debug("Using PLAIN mechanism.");
+
+ return new PlainClient(authorizationId, (String) uinfo[0], (byte[]) uinfo[1]);
+ }
+ }
+
+ /**
+ * Returns an array of names of mechanisms that match the specified
+ * mechanism selection policies.
+ *
+ * @param props The possibly null set of properties used to specify the
+ * security policy of the SASL mechanisms. For example, if <tt>props</tt>
+ * contains the <tt>Sasl.POLICY_NOPLAINTEXT</tt> property with the value
+ * <tt>"true"</tt>, then the factory must not return any SASL mechanisms
+ * that are susceptible to simple plain passive attacks.
+ * See the <tt>Sasl</tt> class for a complete list of policy properties.
+ * Non-policy related properties, if present in <tt>props</tt>, are ignored.
+ *
+ * @return A non-null array containing a IANA-registered SASL mechanism names.
+ */
+ public String[] getMechanismNames(Map props)
+ {
+ //log.debug("public String[] getMechanismNames(Map props = " + props + "): called");
+
+ // Used to build up the valid mechanisms in.
+ List validMechanisms = new ArrayList();
+
+ // Transform the Sasl properties into a set of bit mapped flags indicating the required properties of the
+ // encryption mechanism employed.
+ int requiredFlags = bitMapSaslProperties(props);
+ //log.debug("requiredFlags = " + requiredFlags);
+
+ // Scan down the list of supported mechanisms filtering in only those that satisfy all of the desired
+ // encryption properties.
+ for (int i = 0; i < SUPPORTED_MECHANISMS.length; i++)
+ {
+ int mechanismFlags = SUPPPORTED_MECHANISMS_POLICIES[i];
+ //log.debug("mechanismFlags = " + mechanismFlags);
+
+ // Check if the current mechanism contains all of the required flags.
+ if ((requiredFlags & ~mechanismFlags) == 0)
+ {
+ //log.debug("Mechanism " + SUPPORTED_MECHANISMS[i] + " meets the required properties.");
+ validMechanisms.add(SUPPORTED_MECHANISMS[i]);
+ }
+ }
+
+ String[] result = (String[]) validMechanisms.toArray(new String[validMechanisms.size()]);
+
+ //log.debug("result = " + PrettyPrintingUtils.printArray(result));
+
+ return result;
+ }
+
+ /**
+ * Transforms a set of Sasl properties, defined using the property names in javax.security.sasl.Sasl, into
+ * a bit mapped set of property flags encoded using the bit mapping constants defined in this class.
+ *
+ * @param properties The Sasl properties to bit map.
+ *
+ * @return A set of bit mapped properties encoded in an integer.
+ */
+ private int bitMapSaslProperties(Map properties)
+ {
+ //log.debug("private int bitMapSaslProperties(Map properties = " + properties + "): called");
+
+ int result = 0;
+
+ // No flags set if no properties are set.
+ if (properties == null)
+ {
+ return result;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOPLAINTEXT)))
+ {
+ result |= NOPLAINTEXT;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOACTIVE)))
+ {
+ result |= NOACTIVE;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NODICTIONARY)))
+ {
+ result |= NODICTIONARY;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_NOANONYMOUS)))
+ {
+ result |= NOANONYMOUS;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_FORWARD_SECRECY)))
+ {
+ result |= FORWARD_SECRECY;
+ }
+
+ if ("true".equalsIgnoreCase((String) properties.get(Sasl.POLICY_PASS_CREDENTIALS)))
+ {
+ result |= PASS_CREDENTIALS;
+ }
+
+ return result;
+ }
+
+ /**
+ * Uses the specified call back handler to query for the users log in name and password.
+ *
+ * @param prefix A prefix to prepend onto the username and password queries.
+ * @param authorizationId The default autorhization name.
+ * @param cbh The call back handler.
+ *
+ * @return The username and password from the callback.
+ *
+ * @throws SaslException If the callback fails for any reason.
+ */
+ private Object[] getUserInfo(String prefix, String authorizationId, CallbackHandler cbh) throws SaslException
+ {
+ // Check that the callback handler is defined.
+ if (cbh == null)
+ {
+ throw new SaslException("Callback handler to get username/password required.");
+ }
+
+ try
+ {
+ String userPrompt = prefix + " authentication id: ";
+ String passwdPrompt = prefix + " password: ";
+
+ NameCallback ncb =
+ (authorizationId == null) ? new NameCallback(userPrompt) : new NameCallback(userPrompt, authorizationId);
+ PasswordCallback pcb = new PasswordCallback(passwdPrompt, false);
+
+ // Ask the call back handler to get the users name and password.
+ cbh.handle(new Callback[] { ncb, pcb });
+
+ char[] pw = pcb.getPassword();
+
+ byte[] bytepw;
+ String authId;
+
+ if (pw != null)
+ {
+ bytepw = new String(pw).getBytes("UTF8");
+ pcb.clearPassword();
+ }
+ else
+ {
+ bytepw = null;
+ }
+
+ authId = ncb.getName();
+
+ return new Object[] { authId, bytepw };
+ }
+ catch (IOException e)
+ {
+ throw new SaslException("Cannot get password.", e);
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ throw new SaslException("Cannot get userid/password.", e);
+ }
+ }
+}
diff --git a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java
index 7d15f03329..4f890ffed5 100644
--- a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java
+++ b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/CramMD5Client.java
@@ -1,347 +1,347 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sasl;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-/**
- * Implements the CRAM-MD5 SASL mechanism.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Concatenate the user id and password hashed by a challenge string as the challenge response.
- * <tr><td> Ensure password is wiped once a challenge has been processed.
- * </table>
- */
-public class CramMD5Client implements SaslClient
-{
- /** Defines the HMAC block size. */
- private static final int MD5_BLOCKSIZE = 64;
-
- /** Flag used to indicate that the authentication has completed. */
- private boolean completed = false;
-
- private String authenticationId;
- private byte[] password;
-
- /**
- * Creates a PLAIN SASL client for an authorization id, authentication id and password.
- *
- * @param authenticationId The authentication id.
- * @param password The password.
- *
- * @throws SaslException If the authentication id or password is null.
- */
- CramMD5Client(String authenticationId, byte[] password) throws SaslException
- {
- // Check that a username and password are specified.
- if ((authenticationId == null) || (password == null))
- {
- throw new SaslException("CRAM: authentication id and password must be specified");
- }
-
- // Keep the log in credentials.
- this.authenticationId = authenticationId;
- this.password = password;
- }
-
- /**
- * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
- *
- * @return A non-null string representing the IANA-registered mechanism name.
- */
- public String getMechanismName()
- {
- return "CRAM-MD5";
- }
-
- /**
- * Determines whether this mechanism has an optional initial response. If true, caller should call
- * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
- *
- * <p/>CRAM-MD5 has no intial response.
- *
- * @return true if this mechanism has an initial response.
- */
- public boolean hasInitialResponse()
- {
- return false;
- }
-
- /**
- * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
- * authentication process, this method is called to prepare an appropriate next response to submit to the server.
- *
- * <p/>The initial response for the SASL command, for the CRAM-MD5 mechanism is the concatenation of authentication
- * ID and password HMAC-MD5 hashed by the server challenge.
- *
- * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
- *
- * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
- * status and the challenge only contains data for the client to update its state and no response
- * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
- * response with no data.
- *
- * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
- * response.
- */
- public byte[] evaluateChallenge(byte[] challenge) throws SaslException
- {
- // Check that the authentication has not already been performed.
- if (completed)
- {
- throw new IllegalStateException("CRAM-MD5 authentication already completed.");
- }
-
- // Check if the password is null, this will be the case if a previous attempt to authenticated failed.
- if (password == null)
- {
- throw new IllegalStateException("CRAM-MD5 authentication previously aborted due to error.");
- }
-
- // Generate a keyed-MD5 digest from the user's password keyed by the challenge bytes.
- try
- {
- String digest = hmac_md5(password, challenge);
- String result = authenticationId + " " + digest;
-
- completed = true;
-
- return result.getBytes("UTF8");
- }
- catch (java.security.NoSuchAlgorithmException e)
- {
- throw new SaslException("MD5 algorithm not available on platform", e);
- }
- catch (java.io.UnsupportedEncodingException e)
- {
- throw new SaslException("UTF8 not available on platform", e);
- }
- finally
- {
- clearPassword();
- }
- }
-
- /**
- * Determines whether the authentication exchange has completed. This method may be called at any time, but
- * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
- * manner) that the exchange has completed.
- *
- * @return true if the authentication exchange has completed; false otherwise.
- */
- public boolean isComplete()
- {
- return completed;
- }
-
- /**
- * Unwraps a byte array received from the server. This method can be called only after the authentication exchange
- * has completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has
- * negotiated integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is
- * thrown.
- *
- * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
- * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
- * to use.
- *
- * @param incoming A non-null byte array containing the encoded bytes from the server.
- * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
- * @param len The number of bytes from <tt>incoming</tt> to use.
- *
- * @return A non-null byte array containing the decoded bytes.
- *
- * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
- * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
- * protection has neither integrity nor privacy.
- */
- public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
- {
- throw new SaslException("CRAM-MD5 does not support quality of protection.");
- }
-
- /**
- * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
- * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
- * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
- *
- * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
- * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
- * <tt>outgoing</tt> to use.
- *
- * @param outgoing A non-null byte array containing the bytes to encode.
- * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
- * @param len The number of bytes from <tt>outgoing</tt> to use.
- *
- * @return A non-null byte array containing the encoded bytes.
- *
- * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
- * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
- * protection has neither integrity nor privacy.
- */
- public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
- {
- throw new SaslException("CRAM-MD5 does not support quality of protection.");
- }
-
- /**
- * Retrieves the negotiated property. This method can be called only after the authentication exchange has
- * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
- *
- * @param propName The non-null property name.
- *
- * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
- * this mechanism.
- *
- * @throws IllegalStateException If this authentication exchange has not completed.
- */
- public Object getNegotiatedProperty(String propName)
- {
- if (completed)
- {
- if (propName.equals(Sasl.QOP))
- {
- return "auth";
- }
- else
- {
- return null;
- }
- }
- else
- {
- throw new IllegalStateException("CRAM-MD5 authentication not completed");
- }
- }
-
- /**
- * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
- * method invalidates the SaslClient instance. This method is idempotent.
- *
- * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
- */
- public void dispose() throws SaslException
- { }
-
- /*
- * Hashes its input arguments according to HMAC-MD5 (RFC 2104) and returns the resulting digest in its ASCII
- * representation.
- *
- * <p/> The HMAC-MD5 function is described as follows:
- * <p/><pre>
- * MD5(key XOR opad, MD5(key XOR ipad, text))
- * </pre>
- *
- * <p/>Where key is an n byte key, ipad is the byte 0x36 repeated 64 times, opad is the byte 0x5c repeated 64 times
- * and text is the data to be protected.
- *
- * @param key The key to hash by.
- * @param text The plain text to hash.
- *
- * @return The hashed text.
- *
- * @throws NoSuchAlgorithmException If the Java platform does not supply an MD5 implementation.
- */
- private static final String hmac_md5(byte[] key, byte[] text) throws NoSuchAlgorithmException
- {
- MessageDigest md5 = MessageDigest.getInstance("MD5");
-
- /* digest the key if longer than 64 bytes */
- if (key.length > 64)
- {
- key = md5.digest(key);
- }
-
- byte[] ipad = new byte[MD5_BLOCKSIZE]; /* inner padding */
- byte[] opad = new byte[MD5_BLOCKSIZE]; /* outer padding */
- byte[] digest;
- int i;
-
- /* store key in pads */
- for (i = 0; i < MD5_BLOCKSIZE; i++)
- {
- for (; i < key.length; i++)
- {
- ipad[i] = key[i];
- opad[i] = key[i];
- }
-
- ipad[i] = 0x00;
- opad[i] = 0x00;
- }
-
- /* XOR key with pads */
- for (i = 0; i < MD5_BLOCKSIZE; i++)
- {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
- }
-
- /* inner MD5 */
- md5.update(ipad);
- md5.update(text);
- digest = md5.digest();
-
- /* outer MD5 */
- md5.update(opad);
- md5.update(digest);
- digest = md5.digest();
-
- // Get character representation of digest
- StringBuffer digestString = new StringBuffer();
-
- for (i = 0; i < digest.length; i++)
- {
- if ((digest[i] & 0x000000ff) < 0x10)
- {
- digestString.append("0" + Integer.toHexString(digest[i] & 0x000000ff));
- }
- else
- {
- digestString.append(Integer.toHexString(digest[i] & 0x000000ff));
- }
- }
-
- return (digestString.toString());
- }
-
- /**
- * Overwrites the password with zeros.
- */
- private void clearPassword()
- {
- if (password != null)
- {
- // Zero out password.
- for (int i = 0; i < password.length; i++)
- {
- password[i] = (byte) 0;
- }
-
- password = null;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * Implements the CRAM-MD5 SASL mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Concatenate the user id and password hashed by a challenge string as the challenge response.
+ * <tr><td> Ensure password is wiped once a challenge has been processed.
+ * </table>
+ */
+public class CramMD5Client implements SaslClient
+{
+ /** Defines the HMAC block size. */
+ private static final int MD5_BLOCKSIZE = 64;
+
+ /** Flag used to indicate that the authentication has completed. */
+ private boolean completed = false;
+
+ private String authenticationId;
+ private byte[] password;
+
+ /**
+ * Creates a PLAIN SASL client for an authorization id, authentication id and password.
+ *
+ * @param authenticationId The authentication id.
+ * @param password The password.
+ *
+ * @throws SaslException If the authentication id or password is null.
+ */
+ CramMD5Client(String authenticationId, byte[] password) throws SaslException
+ {
+ // Check that a username and password are specified.
+ if ((authenticationId == null) || (password == null))
+ {
+ throw new SaslException("CRAM: authentication id and password must be specified");
+ }
+
+ // Keep the log in credentials.
+ this.authenticationId = authenticationId;
+ this.password = password;
+ }
+
+ /**
+ * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
+ *
+ * @return A non-null string representing the IANA-registered mechanism name.
+ */
+ public String getMechanismName()
+ {
+ return "CRAM-MD5";
+ }
+
+ /**
+ * Determines whether this mechanism has an optional initial response. If true, caller should call
+ * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
+ *
+ * <p/>CRAM-MD5 has no intial response.
+ *
+ * @return true if this mechanism has an initial response.
+ */
+ public boolean hasInitialResponse()
+ {
+ return false;
+ }
+
+ /**
+ * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
+ * authentication process, this method is called to prepare an appropriate next response to submit to the server.
+ *
+ * <p/>The initial response for the SASL command, for the CRAM-MD5 mechanism is the concatenation of authentication
+ * ID and password HMAC-MD5 hashed by the server challenge.
+ *
+ * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
+ *
+ * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
+ * status and the challenge only contains data for the client to update its state and no response
+ * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
+ * response with no data.
+ *
+ * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
+ * response.
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ // Check that the authentication has not already been performed.
+ if (completed)
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication already completed.");
+ }
+
+ // Check if the password is null, this will be the case if a previous attempt to authenticated failed.
+ if (password == null)
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication previously aborted due to error.");
+ }
+
+ // Generate a keyed-MD5 digest from the user's password keyed by the challenge bytes.
+ try
+ {
+ String digest = hmac_md5(password, challenge);
+ String result = authenticationId + " " + digest;
+
+ completed = true;
+
+ return result.getBytes("UTF8");
+ }
+ catch (java.security.NoSuchAlgorithmException e)
+ {
+ throw new SaslException("MD5 algorithm not available on platform", e);
+ }
+ catch (java.io.UnsupportedEncodingException e)
+ {
+ throw new SaslException("UTF8 not available on platform", e);
+ }
+ finally
+ {
+ clearPassword();
+ }
+ }
+
+ /**
+ * Determines whether the authentication exchange has completed. This method may be called at any time, but
+ * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
+ * manner) that the exchange has completed.
+ *
+ * @return true if the authentication exchange has completed; false otherwise.
+ */
+ public boolean isComplete()
+ {
+ return completed;
+ }
+
+ /**
+ * Unwraps a byte array received from the server. This method can be called only after the authentication exchange
+ * has completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has
+ * negotiated integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is
+ * thrown.
+ *
+ * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
+ * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
+ * to use.
+ *
+ * @param incoming A non-null byte array containing the encoded bytes from the server.
+ * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>incoming</tt> to use.
+ *
+ * @return A non-null byte array containing the decoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("CRAM-MD5 does not support quality of protection.");
+ }
+
+ /**
+ * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
+ * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
+ * <tt>outgoing</tt> to use.
+ *
+ * @param outgoing A non-null byte array containing the bytes to encode.
+ * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>outgoing</tt> to use.
+ *
+ * @return A non-null byte array containing the encoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("CRAM-MD5 does not support quality of protection.");
+ }
+
+ /**
+ * Retrieves the negotiated property. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * @param propName The non-null property name.
+ *
+ * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
+ * this mechanism.
+ *
+ * @throws IllegalStateException If this authentication exchange has not completed.
+ */
+ public Object getNegotiatedProperty(String propName)
+ {
+ if (completed)
+ {
+ if (propName.equals(Sasl.QOP))
+ {
+ return "auth";
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("CRAM-MD5 authentication not completed");
+ }
+ }
+
+ /**
+ * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
+ * method invalidates the SaslClient instance. This method is idempotent.
+ *
+ * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
+ */
+ public void dispose() throws SaslException
+ { }
+
+ /*
+ * Hashes its input arguments according to HMAC-MD5 (RFC 2104) and returns the resulting digest in its ASCII
+ * representation.
+ *
+ * <p/> The HMAC-MD5 function is described as follows:
+ * <p/><pre>
+ * MD5(key XOR opad, MD5(key XOR ipad, text))
+ * </pre>
+ *
+ * <p/>Where key is an n byte key, ipad is the byte 0x36 repeated 64 times, opad is the byte 0x5c repeated 64 times
+ * and text is the data to be protected.
+ *
+ * @param key The key to hash by.
+ * @param text The plain text to hash.
+ *
+ * @return The hashed text.
+ *
+ * @throws NoSuchAlgorithmException If the Java platform does not supply an MD5 implementation.
+ */
+ private static final String hmac_md5(byte[] key, byte[] text) throws NoSuchAlgorithmException
+ {
+ MessageDigest md5 = MessageDigest.getInstance("MD5");
+
+ /* digest the key if longer than 64 bytes */
+ if (key.length > 64)
+ {
+ key = md5.digest(key);
+ }
+
+ byte[] ipad = new byte[MD5_BLOCKSIZE]; /* inner padding */
+ byte[] opad = new byte[MD5_BLOCKSIZE]; /* outer padding */
+ byte[] digest;
+ int i;
+
+ /* store key in pads */
+ for (i = 0; i < MD5_BLOCKSIZE; i++)
+ {
+ for (; i < key.length; i++)
+ {
+ ipad[i] = key[i];
+ opad[i] = key[i];
+ }
+
+ ipad[i] = 0x00;
+ opad[i] = 0x00;
+ }
+
+ /* XOR key with pads */
+ for (i = 0; i < MD5_BLOCKSIZE; i++)
+ {
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+ /* inner MD5 */
+ md5.update(ipad);
+ md5.update(text);
+ digest = md5.digest();
+
+ /* outer MD5 */
+ md5.update(opad);
+ md5.update(digest);
+ digest = md5.digest();
+
+ // Get character representation of digest
+ StringBuffer digestString = new StringBuffer();
+
+ for (i = 0; i < digest.length; i++)
+ {
+ if ((digest[i] & 0x000000ff) < 0x10)
+ {
+ digestString.append("0" + Integer.toHexString(digest[i] & 0x000000ff));
+ }
+ else
+ {
+ digestString.append(Integer.toHexString(digest[i] & 0x000000ff));
+ }
+ }
+
+ return (digestString.toString());
+ }
+
+ /**
+ * Overwrites the password with zeros.
+ */
+ private void clearPassword()
+ {
+ if (password != null)
+ {
+ // Zero out password.
+ for (int i = 0; i < password.length; i++)
+ {
+ password[i] = (byte) 0;
+ }
+
+ password = null;
+ }
+ }
+}
diff --git a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java
index 97e607c57e..f5a9f150bb 100644
--- a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java
+++ b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/PlainClient.java
@@ -1,275 +1,275 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sasl;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-/**
- * Implements the PLAIN SASL mechanism.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Concatenate the user id and password in plain text as the challenge respose.
- * <tr><td> Ensure password is wiped once a challenge has been processed.
- * </table>
- */
-public class PlainClient implements SaslClient
-{
- /** Flag used to indicate that the authentication has completed. */
- private boolean completed = false;
-
- private String authorizationId;
- private String authenticationId;
- private byte[] password;
-
- private static byte SEPERATOR = 0; // US-ASCII <NUL>
-
- /**
- * Creates a PLAIN SASL client for an authorization id, authentication id and password.
- *
- * @param authorizationId The authorization id. May be null.
- * @param authenticationId The authentication id.
- * @param password The password.
- *
- * @throws SaslException If the authentication id or password is null.
- */
- PlainClient(String authorizationId, String authenticationId, byte[] password) throws SaslException
- {
- // Check that a username and password are specified.
- if ((authenticationId == null) || (password == null))
- {
- throw new SaslException("PLAIN: authentication ID and password must be specified");
- }
-
- // Keep the log in credentials.
- this.authorizationId = authorizationId;
- this.authenticationId = authenticationId;
- this.password = password;
- }
-
- /**
- * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
- *
- * @return A non-null string representing the IANA-registered mechanism name.
- */
- public String getMechanismName()
- {
- return "PLAIN";
- }
-
- /**
- * Determines whether this mechanism has an optional initial response. If true, caller should call
- * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
- *
- * @return true if this mechanism has an initial response.
- */
- public boolean hasInitialResponse()
- {
- return true;
- }
-
- /**
- * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
- * authentication process, this method is called to prepare an appropriate next response to submit to the server.
- *
- * <p/>The initial response for the SASL command, for the PLAIN mechanism is the concatenation of authorization ID,
- * authentication ID and password, with each component separated by the US-ASCII <NUL> byte.
- *
- * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
- *
- * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
- * status and the challenge only contains data for the client to update its state and no response
- * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
- * response with no data.
- *
- * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
- * response.
- */
- public byte[] evaluateChallenge(byte[] challenge) throws SaslException
- {
- // Check that the authentication has not already been performed.
- if (completed)
- {
- throw new IllegalStateException("PLAIN authentication already completed");
- }
-
- try
- {
- // Get the authorization and authentication ids in bytes.
- byte[] authorizationBytes = (authorizationId != null) ? authorizationId.getBytes("UTF8") : null;
- byte[] authenticationBytes = authenticationId.getBytes("UTF8");
-
- // Create an array big enough to hold the results.
- byte[] result =
- new byte[password.length + authenticationBytes.length + 2
- + ((authorizationBytes == null) ? 0 : authorizationBytes.length)];
-
- // Copy the authorization id, authentication id and password into the results.
- int pos = 0;
- if (authorizationBytes != null)
- {
- System.arraycopy(authorizationBytes, 0, result, 0, authorizationBytes.length);
- pos = authorizationBytes.length;
- }
-
- result[pos++] = SEPERATOR;
- System.arraycopy(authenticationBytes, 0, result, pos, authenticationBytes.length);
-
- pos += authenticationBytes.length;
- result[pos++] = SEPERATOR;
-
- System.arraycopy(password, 0, result, pos, password.length);
-
- completed = true;
-
- return result;
- }
- catch (java.io.UnsupportedEncodingException e)
- {
- throw new SaslException("Cannot get UTF-8 encoding of ids", e);
- }
- finally
- {
- clearPassword();
- }
- }
-
- /**
- * Determines whether the authentication exchange has completed. This method may be called at any time, but
- * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
- * manner) that the exchange has completed.
- *
- * @return true if the authentication exchange has completed; false otherwise.
- */
- public boolean isComplete()
- {
- return completed;
- }
-
- /**
- * Unwraps a byte array received from the server. This method can be called only after the authentication exchange has
- * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
- * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
- *
- * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
- * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
- * to use.
- *
- * @param incoming A non-null byte array containing the encoded bytes
- * from the server.
- * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
- * @param len The number of bytes from <tt>incoming</tt> to use.
- *
- * @return A non-null byte array containing the decoded bytes.
- *
- * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
- * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
- * protection has neither integrity nor privacy.
- */
- public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
- {
- throw new SaslException("PLAIN does not support quality of protection.");
- }
-
- /**
- * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
- * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
- * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
- *
- * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
- * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
- * <tt>outgoing</tt> to use.
- *
- * @param outgoing A non-null byte array containing the bytes to encode.
- * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
- * @param len The number of bytes from <tt>outgoing</tt> to use.
- *
- * @return A non-null byte array containing the encoded bytes.
- *
- * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
- * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
- * protection has neither integrity nor privacy.
- */
- public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
- {
- throw new SaslException("PLAIN does not support quality of protection.");
- }
-
- /**
- * Retrieves the negotiated property. This method can be called only after the authentication exchange has
- * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
- *
- * @param propName The non-null property name.
- *
- * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
- * this mechanism.
- *
- * @throws IllegalStateException If this authentication exchange has not completed.
- */
- public Object getNegotiatedProperty(String propName)
- {
- if (completed)
- {
- if (propName.equals(Sasl.QOP))
- {
- return "auth";
- }
- else
- {
- return null;
- }
- }
- else
- {
- throw new IllegalStateException("PLAIN authentication not completed");
- }
- }
-
- /**
- * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
- * method invalidates the SaslClient instance. This method is idempotent.
- *
- * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
- */
- public void dispose() throws SaslException
- {
- clearPassword();
- }
-
- /**
- * Overwrites the password with zeros.
- */
- private void clearPassword()
- {
- if (password != null)
- {
- // Zero out password.
- for (int i = 0; i < password.length; i++)
- {
- password[i] = (byte) 0;
- }
-
- password = null;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+/**
+ * Implements the PLAIN SASL mechanism.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Concatenate the user id and password in plain text as the challenge respose.
+ * <tr><td> Ensure password is wiped once a challenge has been processed.
+ * </table>
+ */
+public class PlainClient implements SaslClient
+{
+ /** Flag used to indicate that the authentication has completed. */
+ private boolean completed = false;
+
+ private String authorizationId;
+ private String authenticationId;
+ private byte[] password;
+
+ private static byte SEPERATOR = 0; // US-ASCII <NUL>
+
+ /**
+ * Creates a PLAIN SASL client for an authorization id, authentication id and password.
+ *
+ * @param authorizationId The authorization id. May be null.
+ * @param authenticationId The authentication id.
+ * @param password The password.
+ *
+ * @throws SaslException If the authentication id or password is null.
+ */
+ PlainClient(String authorizationId, String authenticationId, byte[] password) throws SaslException
+ {
+ // Check that a username and password are specified.
+ if ((authenticationId == null) || (password == null))
+ {
+ throw new SaslException("PLAIN: authentication ID and password must be specified");
+ }
+
+ // Keep the log in credentials.
+ this.authorizationId = authorizationId;
+ this.authenticationId = authenticationId;
+ this.password = password;
+ }
+
+ /**
+ * Returns the IANA-registered mechanism name of this SASL client. (e.g. "CRAM-MD5", "GSSAPI").
+ *
+ * @return A non-null string representing the IANA-registered mechanism name.
+ */
+ public String getMechanismName()
+ {
+ return "PLAIN";
+ }
+
+ /**
+ * Determines whether this mechanism has an optional initial response. If true, caller should call
+ * <tt>evaluateChallenge()</tt> with an empty array to get the initial response.
+ *
+ * @return true if this mechanism has an initial response.
+ */
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ /**
+ * Evaluates the challenge data and generates a response. If a challenge is received from the server during the
+ * authentication process, this method is called to prepare an appropriate next response to submit to the server.
+ *
+ * <p/>The initial response for the SASL command, for the PLAIN mechanism is the concatenation of authorization ID,
+ * authentication ID and password, with each component separated by the US-ASCII <NUL> byte.
+ *
+ * @param challenge The non-null challenge sent from the server. The challenge array may have zero length.
+ *
+ * @return The possibly null reponse to send to the server. It is null if the challenge accompanied a "SUCCESS"
+ * status and the challenge only contains data for the client to update its state and no response
+ * needs to be sent to the server. The response is a zero-length byte array if the client is to send a
+ * response with no data.
+ *
+ * @throws javax.security.sasl.SaslException If an error occurred while processing the challenge or generating a
+ * response.
+ */
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ // Check that the authentication has not already been performed.
+ if (completed)
+ {
+ throw new IllegalStateException("PLAIN authentication already completed");
+ }
+
+ try
+ {
+ // Get the authorization and authentication ids in bytes.
+ byte[] authorizationBytes = (authorizationId != null) ? authorizationId.getBytes("UTF8") : null;
+ byte[] authenticationBytes = authenticationId.getBytes("UTF8");
+
+ // Create an array big enough to hold the results.
+ byte[] result =
+ new byte[password.length + authenticationBytes.length + 2
+ + ((authorizationBytes == null) ? 0 : authorizationBytes.length)];
+
+ // Copy the authorization id, authentication id and password into the results.
+ int pos = 0;
+ if (authorizationBytes != null)
+ {
+ System.arraycopy(authorizationBytes, 0, result, 0, authorizationBytes.length);
+ pos = authorizationBytes.length;
+ }
+
+ result[pos++] = SEPERATOR;
+ System.arraycopy(authenticationBytes, 0, result, pos, authenticationBytes.length);
+
+ pos += authenticationBytes.length;
+ result[pos++] = SEPERATOR;
+
+ System.arraycopy(password, 0, result, pos, password.length);
+
+ completed = true;
+
+ return result;
+ }
+ catch (java.io.UnsupportedEncodingException e)
+ {
+ throw new SaslException("Cannot get UTF-8 encoding of ids", e);
+ }
+ finally
+ {
+ clearPassword();
+ }
+ }
+
+ /**
+ * Determines whether the authentication exchange has completed. This method may be called at any time, but
+ * typically, it will not be called until the caller has received indication from the server (in a protocol-specific
+ * manner) that the exchange has completed.
+ *
+ * @return true if the authentication exchange has completed; false otherwise.
+ */
+ public boolean isComplete()
+ {
+ return completed;
+ }
+
+ /**
+ * Unwraps a byte array received from the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/><tt>incoming</tt> is the contents of the SASL buffer as defined in RFC 2222 without the leading four octet
+ * field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of <tt>incoming</tt>
+ * to use.
+ *
+ * @param incoming A non-null byte array containing the encoded bytes
+ * from the server.
+ * @param offset The starting position at <tt>incoming</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>incoming</tt> to use.
+ *
+ * @return A non-null byte array containing the decoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>incoming</tt> cannot be successfully unwrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ throw new SaslException("PLAIN does not support quality of protection.");
+ }
+
+ /**
+ * Wraps a byte array to be sent to the server. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true) and only if the authentication exchange has negotiated
+ * integrity and/or privacy as the quality of protection; otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * <p/>The result of this method will make up the contents of the SASL buffer as defined in RFC 2222 without the
+ * leading four octet field that represents the length. <tt>offset</tt> and <tt>len</tt> specify the portion of
+ * <tt>outgoing</tt> to use.
+ *
+ * @param outgoing A non-null byte array containing the bytes to encode.
+ * @param offset The starting position at <tt>outgoing</tt> of the bytes to use.
+ * @param len The number of bytes from <tt>outgoing</tt> to use.
+ *
+ * @return A non-null byte array containing the encoded bytes.
+ *
+ * @throws javax.security.sasl.SaslException If <tt>outgoing</tt> cannot be successfully wrapped.
+ * @throws IllegalStateException If the authentication exchange has not completed, or if the negotiated quality of
+ * protection has neither integrity nor privacy.
+ */
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ throw new SaslException("PLAIN does not support quality of protection.");
+ }
+
+ /**
+ * Retrieves the negotiated property. This method can be called only after the authentication exchange has
+ * completed (i.e., when <tt>isComplete()</tt> returns true); otherwise, an <tt>IllegalStateException</tt> is thrown.
+ *
+ * @param propName The non-null property name.
+ *
+ * @return The value of the negotiated property. If null, the property was not negotiated or is not applicable to
+ * this mechanism.
+ *
+ * @throws IllegalStateException If this authentication exchange has not completed.
+ */
+ public Object getNegotiatedProperty(String propName)
+ {
+ if (completed)
+ {
+ if (propName.equals(Sasl.QOP))
+ {
+ return "auth";
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("PLAIN authentication not completed");
+ }
+ }
+
+ /**
+ * Disposes of any system resources or security-sensitive information the SaslClient might be using. Invoking this
+ * method invalidates the SaslClient instance. This method is idempotent.
+ *
+ * @throws javax.security.sasl.SaslException If a problem was encountered while disposing the resources.
+ */
+ public void dispose() throws SaslException
+ {
+ clearPassword();
+ }
+
+ /**
+ * Overwrites the password with zeros.
+ */
+ private void clearPassword()
+ {
+ if (password != null)
+ {
+ // Zero out password.
+ for (int i = 0; i < password.length; i++)
+ {
+ password[i] = (byte) 0;
+ }
+
+ password = null;
+ }
+ }
+}
diff --git a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java
index f9a5c42c3d..ef075a0cad 100644
--- a/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java
+++ b/qpid/java/client-java14/src/main/java/org/apache/qpid/sasl/Provider.java
@@ -1,61 +1,61 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sasl;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import org.apache.log4j.Logger;
-
-/**
- * A SASL provider for Java 1.4. Declares the capabilities of this implementation, which supports PLAIN and CRAM-MD5
- * client implementations only.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Declare PLAIN SASL support.
- * <tr><td> Declare CRAM-MD5 SASL support.
- * </table>
- */
-public class Provider extends java.security.Provider
-{
- //Logger log = Logger.getLogger(Provider.class);
-
- private static final String info = "Qpid SASL provider" + "(implements client mechanisms for: PLAIN, CRAM-MD5)";
-
- public Provider()
- {
- super("QpidSASL", 1.4, info);
-
- //log.debug("public Provider(): called");
-
- AccessController.doPrivileged(new PrivilegedAction()
- {
- public Object run()
- {
- put("SaslClientFactory.PLAIN", "org.apache.qpid.sasl.ClientFactoryImpl");
- put("SaslClientFactory.CRAM-MD5", "org.apache.qpid.sasl.ClientFactoryImpl");
-
- return null;
- }
- });
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sasl;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A SASL provider for Java 1.4. Declares the capabilities of this implementation, which supports PLAIN and CRAM-MD5
+ * client implementations only.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Declare PLAIN SASL support.
+ * <tr><td> Declare CRAM-MD5 SASL support.
+ * </table>
+ */
+public class Provider extends java.security.Provider
+{
+ //Logger log = Logger.getLogger(Provider.class);
+
+ private static final String info = "Qpid SASL provider" + "(implements client mechanisms for: PLAIN, CRAM-MD5)";
+
+ public Provider()
+ {
+ super("QpidSASL", 1.4, info);
+
+ //log.debug("public Provider(): called");
+
+ AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ put("SaslClientFactory.PLAIN", "org.apache.qpid.sasl.ClientFactoryImpl");
+ put("SaslClientFactory.CRAM-MD5", "org.apache.qpid.sasl.ClientFactoryImpl");
+
+ return null;
+ }
+ });
+ }
+}
diff --git a/qpid/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java b/qpid/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java
index 468beda5b5..77cc79bc49 100644
--- a/qpid/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java
+++ b/qpid/java/client-java14/src/test/java/org/apache/qpid/test/integration/client/ConnectionTest.java
@@ -1,66 +1,66 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.integration.client;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-
-import org.apache.qpid.client.AMQConnection;
-
-/**
- * Implements a trivial broker connection test, to a broker on the default port on localhost, to check that SASL
- * authentication works.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check that a connection to a broker can be established.
- * </table>
- */
-public class ConnectionTest extends TestCase
-{
- private String BROKER_URL = "tcp://localhost:5672";
-
- public ConnectionTest(String name)
- {
- super(name);
- }
-
- /** Check that a connection to a broker can be established. */
- public void testConnection() throws Exception
- {
- // Open a connection to the broker and close it again.
- AMQConnection conn = new AMQConnection(BROKER_URL, "guest", "guest", "clientid", "test");
- conn.close();
- }
-
- protected void setUp()
- {
- NDC.push(getName());
- }
-
- protected void tearDown()
- {
- NDC.pop();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.integration.client;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.client.AMQConnection;
+
+/**
+ * Implements a trivial broker connection test, to a broker on the default port on localhost, to check that SASL
+ * authentication works.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check that a connection to a broker can be established.
+ * </table>
+ */
+public class ConnectionTest extends TestCase
+{
+ private String BROKER_URL = "tcp://localhost:5672";
+
+ public ConnectionTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check that a connection to a broker can be established. */
+ public void testConnection() throws Exception
+ {
+ // Open a connection to the broker and close it again.
+ AMQConnection conn = new AMQConnection(BROKER_URL, "guest", "guest", "clientid", "test");
+ conn.close();
+ }
+
+ protected void setUp()
+ {
+ NDC.push(getName());
+ }
+
+ protected void tearDown()
+ {
+ NDC.pop();
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSessionAdapter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSessionAdapter.java
index 93f10761e2..7e257e0c20 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSessionAdapter.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSessionAdapter.java
@@ -1,26 +1,26 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client;
-
-public interface AMQSessionAdapter
-{
- public AMQSession getSession();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client;
+
+public interface AMQSessionAdapter
+{
+ public AMQSession getSession();
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQUndefinedDestination.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQUndefinedDestination.java
index 768e2862b3..fa2afb3ee4 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQUndefinedDestination.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQUndefinedDestination.java
@@ -1,40 +1,40 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client;
-
-import org.apache.qpid.framing.AMQShortString;
-
-public class AMQUndefinedDestination extends AMQDestination
-{
-
- private static final AMQShortString UNKNOWN_EXCHANGE_CLASS = new AMQShortString("unknown");
-
-
- public AMQUndefinedDestination(AMQShortString exchange, AMQShortString routingKey, AMQShortString queueName)
- {
- super(exchange, UNKNOWN_EXCHANGE_CLASS, routingKey, queueName);
- }
-
- public boolean isNameRequired()
- {
- return getAMQQueueName() == null;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client;
+
+import org.apache.qpid.framing.AMQShortString;
+
+public class AMQUndefinedDestination extends AMQDestination
+{
+
+ private static final AMQShortString UNKNOWN_EXCHANGE_CLASS = new AMQShortString("unknown");
+
+
+ public AMQUndefinedDestination(AMQShortString exchange, AMQShortString routingKey, AMQShortString queueName)
+ {
+ super(exchange, UNKNOWN_EXCHANGE_CLASS, routingKey, queueName);
+ }
+
+ public boolean isNameRequired()
+ {
+ return getAMQQueueName() == null;
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java b/qpid/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
index 8cb285c1ac..7cc548915c 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/CustomJMSXProperty.java
@@ -1,66 +1,66 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-
-import org.apache.qpid.framing.AMQShortString;
-
-public enum CustomJMSXProperty
-{
- JMS_AMQP_NULL,
- JMS_QPID_DESTTYPE,
- JMSXGroupID,
- JMSXGroupSeq,
- JMSXUserID;
-
-
- private final AMQShortString _nameAsShortString;
-
- CustomJMSXProperty()
- {
- _nameAsShortString = new AMQShortString(toString());
- }
-
- public AMQShortString getShortStringName()
- {
- return _nameAsShortString;
- }
-
- private static Enumeration _names;
-
- public static synchronized Enumeration asEnumeration()
- {
- if(_names == null)
- {
- CustomJMSXProperty[] properties = values();
- ArrayList<String> nameList = new ArrayList<String>(properties.length);
- for(CustomJMSXProperty property : properties)
- {
- nameList.add(property.toString());
- }
- _names = Collections.enumeration(nameList);
- }
- return _names;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import org.apache.qpid.framing.AMQShortString;
+
+public enum CustomJMSXProperty
+{
+ JMS_AMQP_NULL,
+ JMS_QPID_DESTTYPE,
+ JMSXGroupID,
+ JMSXGroupSeq,
+ JMSXUserID;
+
+
+ private final AMQShortString _nameAsShortString;
+
+ CustomJMSXProperty()
+ {
+ _nameAsShortString = new AMQShortString(toString());
+ }
+
+ public AMQShortString getShortStringName()
+ {
+ return _nameAsShortString;
+ }
+
+ private static Enumeration _names;
+
+ public static synchronized Enumeration asEnumeration()
+ {
+ if(_names == null)
+ {
+ CustomJMSXProperty[] properties = values();
+ ArrayList<String> nameList = new ArrayList<String>(properties.length);
+ for(CustomJMSXProperty property : properties)
+ {
+ nameList.add(property.toString());
+ }
+ _names = Collections.enumeration(nameList);
+ }
+ return _names;
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java b/qpid/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
index 03d25aa243..7f8e80c73a 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
@@ -1,38 +1,38 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.client;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-
-/**
- * Provides support for covenience interface implemented by both AMQTemporaryTopic and AMQTemporaryQueue
- * so that operations related to their "temporary-ness" can be abstracted out.
- */
-interface TemporaryDestination extends Destination
-{
-
- public void delete() throws JMSException;
- public AMQSession getSession();
- public boolean isDeleted();
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.client;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+
+/**
+ * Provides support for covenience interface implemented by both AMQTemporaryTopic and AMQTemporaryQueue
+ * so that operations related to their "temporary-ness" can be abstracted out.
+ */
+interface TemporaryDestination extends Destination
+{
+
+ public void delete() throws JMSException;
+ public AMQSession getSession();
+ public boolean isDeleted();
+
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java
index 1ec98efe0e..51cc94965a 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java
@@ -1,75 +1,75 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.client.failover;
-
-import org.apache.qpid.client.AMQConnection;
-
-/**
- * FailoverNoopSupport is a {@link FailoverSupport} implementation that does not really provide any failover support
- * at all. It wraps a {@link FailoverProtectedOperation} but should that operation throw {@link FailoverException} this
- * support class simply re-raises that exception as an IllegalStateException. This support wrapper should only be
- * used where the caller can be certain that the failover protected operation cannot acutally throw a failover exception,
- * for example, because the caller already holds a lock preventing that condition from arising.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Perform a fail-over protected operation raising providing no handling of fail-over conditions.
- * </table>
- */
-public class FailoverNoopSupport<T, E extends Exception> implements FailoverSupport<T, E>
-{
- /** The protected operation that is to be retried in the event of fail-over. */
- FailoverProtectedOperation<T, E> operation;
-
- /** The connection on which the fail-over protected operation is to be performed. */
- AMQConnection connection;
-
- /**
- * Creates an automatic retrying fail-over handler for the specified operation.
- *
- * @param operation The fail-over protected operation to wrap in this handler.
- */
- public FailoverNoopSupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
- {
- this.operation = operation;
- this.connection = con;
- }
-
- /**
- * Delegates to another continuation which is to be provided with fail-over handling.
- *
- * @return The return value from the delegated to continuation.
- * @throws E Any exception that the delegated to continuation may raise.
- */
- public T execute() throws E
- {
- try
- {
- return operation.execute();
- }
- catch (FailoverException e)
- {
- throw new IllegalStateException("Fail-over interupted no-op failover support. "
- + "No-op support should only be used where the caller is certain fail-over cannot occur.", e);
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.client.failover;
+
+import org.apache.qpid.client.AMQConnection;
+
+/**
+ * FailoverNoopSupport is a {@link FailoverSupport} implementation that does not really provide any failover support
+ * at all. It wraps a {@link FailoverProtectedOperation} but should that operation throw {@link FailoverException} this
+ * support class simply re-raises that exception as an IllegalStateException. This support wrapper should only be
+ * used where the caller can be certain that the failover protected operation cannot acutally throw a failover exception,
+ * for example, because the caller already holds a lock preventing that condition from arising.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Perform a fail-over protected operation raising providing no handling of fail-over conditions.
+ * </table>
+ */
+public class FailoverNoopSupport<T, E extends Exception> implements FailoverSupport<T, E>
+{
+ /** The protected operation that is to be retried in the event of fail-over. */
+ FailoverProtectedOperation<T, E> operation;
+
+ /** The connection on which the fail-over protected operation is to be performed. */
+ AMQConnection connection;
+
+ /**
+ * Creates an automatic retrying fail-over handler for the specified operation.
+ *
+ * @param operation The fail-over protected operation to wrap in this handler.
+ */
+ public FailoverNoopSupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
+ {
+ this.operation = operation;
+ this.connection = con;
+ }
+
+ /**
+ * Delegates to another continuation which is to be provided with fail-over handling.
+ *
+ * @return The return value from the delegated to continuation.
+ * @throws E Any exception that the delegated to continuation may raise.
+ */
+ public T execute() throws E
+ {
+ try
+ {
+ return operation.execute();
+ }
+ catch (FailoverException e)
+ {
+ throw new IllegalStateException("Fail-over interupted no-op failover support. "
+ + "No-op support should only be used where the caller is certain fail-over cannot occur.", e);
+ }
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java
index 9a7f43926e..e9c5f24791 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java
@@ -1,49 +1,49 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.client.failover;
-
-/**
- * FailoverProtectedOperation is a continuation for an operation that may throw a {@link FailoverException} because
- * it has been interrupted by the fail-over process. The {@link FailoverRetrySupport} class defines support wrappers
- * for failover protected operations, in order to provide different handling schemes when failovers occurr.
- *
- * <p/>The type of checked exception that the operation may perform has been generified, in order that fail over
- * protected operations can be defined that raise arbitrary exceptions. The actuall exception types used should not
- * be sub-classes of FailoverException, or else catching FailoverException in the {@link FailoverRetrySupport} classes
- * will mask the exception.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Perform an operation that may be interrupted by fail-over.
- * </table>
- */
-public interface FailoverProtectedOperation<T, E extends Exception>
-{
- /**
- * Performs the continuations work.
- *
- * @return Provdes scope for the continuation to return an arbitrary value.
- *
- * @throws FailoverException If the operation is interrupted by a fail-over notification.
- */
- public abstract T execute() throws E, FailoverException;
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.client.failover;
+
+/**
+ * FailoverProtectedOperation is a continuation for an operation that may throw a {@link FailoverException} because
+ * it has been interrupted by the fail-over process. The {@link FailoverRetrySupport} class defines support wrappers
+ * for failover protected operations, in order to provide different handling schemes when failovers occurr.
+ *
+ * <p/>The type of checked exception that the operation may perform has been generified, in order that fail over
+ * protected operations can be defined that raise arbitrary exceptions. The actuall exception types used should not
+ * be sub-classes of FailoverException, or else catching FailoverException in the {@link FailoverRetrySupport} classes
+ * will mask the exception.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Perform an operation that may be interrupted by fail-over.
+ * </table>
+ */
+public interface FailoverProtectedOperation<T, E extends Exception>
+{
+ /**
+ * Performs the continuations work.
+ *
+ * @return Provdes scope for the continuation to return an arbitrary value.
+ *
+ * @throws FailoverException If the operation is interrupted by a fail-over notification.
+ */
+ public abstract T execute() throws E, FailoverException;
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
index e756d7baf9..cf7e978c03 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java
@@ -1,135 +1,135 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.failover;
-
-import org.apache.qpid.client.AMQConnection;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * FailoverRetrySupport is a continuation that wraps another continuation, delaying its execution until it is notified
- * that a blocking condition has been met, and executing the continuation within a mutex. If the continuation fails, due
- * to the original condition being broken, whilst the continuation is waiting for a reponse to a synchronous request,
- * FailoverRetrySupport automatcally rechecks the condition and re-acquires the mutex and re-runs the continution. This
- * automatic retrying is continued until the continuation succeeds, or throws an exception (different to
- * FailoverException, which is used to signal the failure of the original condition).
- *
- * <p/>The blocking condition used is that the connection is not currently failing over, and the mutex used is the
- * connection failover mutex, which guards against the fail-over process being run during fail-over vulnerable methods.
- * These are used like a lock and condition variable.
- *
- * <p/>The wrapped operation may throw a FailoverException, this is an exception that can be raised by a
- * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener}, in response to it being notified that a
- * fail-over wants to start whilst it was waiting. Methods that are vulnerable to fail-over are those that are
- * synchronous, where a failure will prevent them from getting the reply they are waiting for and asynchronous
- * methods that should not be attempted when a fail-over is in progress.
- *
- * <p/>Wrapping a synchronous method in a FailoverRetrySupport will have the effect that the operation will not be
- * started during fail-over, but be delayed until any current fail-over has completed. Should a fail-over process want
- * to start whilst waiting for the synchrnous reply, the FailoverRetrySupport will detect this and rety the operation
- * until it succeeds. Synchronous methods are usually coordinated with a
- * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener} which is notified when a fail-over process wants
- * to start and throws a FailoverException in response to this.
- *
- * <p/>Wrapping an asynchronous method in a FailoverRetrySupport will have the effect that the operation will not be
- * started during fail-over, but be delayed until any current fail-over has completed.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a continuation synchronized on a fail-over lock and condition.
- * <tr><td> Automatically retry the continuation accross fail-overs until it succeeds, or raises an exception.
- * </table>
- *
- * @todo Another continuation. Could use an interface Continuation (as described in other todos, for example, see
- * {@link org.apache.qpid.pool.Job}). Then have a wrapping continuation (this), which blocks on an arbitrary
- * Condition or Latch (specified in constructor call), that this blocks on before calling the wrapped Continuation.
- * Must work on Java 1.4, so check retrotranslator works on Lock/Condition or latch first. Argument and return type
- * to match wrapped condition as type parameters. Rename to AsyncConditionalContinuation or something like that.
- *
- * @todo InterruptedException not handled well.
- */
-public class FailoverRetrySupport<T, E extends Exception> implements FailoverSupport<T, E>
-{
- /** Used for debugging. */
- private static final Logger _log = LoggerFactory.getLogger(FailoverRetrySupport.class);
-
- /** The protected operation that is to be retried in the event of fail-over. */
- FailoverProtectedOperation<T, E> operation;
-
- /** The connection on which the fail-over protected operation is to be performed. */
- AMQConnection connection;
-
- /**
- * Creates an automatic retrying fail-over handler for the specified operation.
- *
- * @param operation The fail-over protected operation to wrap in this handler.
- */
- public FailoverRetrySupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
- {
- this.operation = operation;
- this.connection = con;
- }
-
- /**
- * Delays a continuation until the "not failing over" condition is met on the specified connection. Repeats
- * until the operation throws AMQException or succeeds without being interrupted by fail-over.
- *
- * @return The result of executing the continuation.
- *
- * @throws E Any underlying exception is allowed to fall through.
- */
- public T execute() throws E
- {
- while (true)
- {
- try
- {
- connection.blockUntilNotFailingOver();
- }
- catch (InterruptedException e)
- {
- _log.debug("Interrupted: " + e, e);
-
- return null;
- }
-
- synchronized (connection.getFailoverMutex())
- {
- try
- {
- return operation.execute();
- }
- catch (FailoverException e)
- {
- _log.debug("Failover exception caught during operation: " + e, e);
- }
- catch (IllegalStateException e)
- {
- if (!(e.getMessage().startsWith("Fail-over interupted no-op failover support")))
- {
- throw e;
- }
- }
- }
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.failover;
+
+import org.apache.qpid.client.AMQConnection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FailoverRetrySupport is a continuation that wraps another continuation, delaying its execution until it is notified
+ * that a blocking condition has been met, and executing the continuation within a mutex. If the continuation fails, due
+ * to the original condition being broken, whilst the continuation is waiting for a reponse to a synchronous request,
+ * FailoverRetrySupport automatcally rechecks the condition and re-acquires the mutex and re-runs the continution. This
+ * automatic retrying is continued until the continuation succeeds, or throws an exception (different to
+ * FailoverException, which is used to signal the failure of the original condition).
+ *
+ * <p/>The blocking condition used is that the connection is not currently failing over, and the mutex used is the
+ * connection failover mutex, which guards against the fail-over process being run during fail-over vulnerable methods.
+ * These are used like a lock and condition variable.
+ *
+ * <p/>The wrapped operation may throw a FailoverException, this is an exception that can be raised by a
+ * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener}, in response to it being notified that a
+ * fail-over wants to start whilst it was waiting. Methods that are vulnerable to fail-over are those that are
+ * synchronous, where a failure will prevent them from getting the reply they are waiting for and asynchronous
+ * methods that should not be attempted when a fail-over is in progress.
+ *
+ * <p/>Wrapping a synchronous method in a FailoverRetrySupport will have the effect that the operation will not be
+ * started during fail-over, but be delayed until any current fail-over has completed. Should a fail-over process want
+ * to start whilst waiting for the synchrnous reply, the FailoverRetrySupport will detect this and rety the operation
+ * until it succeeds. Synchronous methods are usually coordinated with a
+ * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener} which is notified when a fail-over process wants
+ * to start and throws a FailoverException in response to this.
+ *
+ * <p/>Wrapping an asynchronous method in a FailoverRetrySupport will have the effect that the operation will not be
+ * started during fail-over, but be delayed until any current fail-over has completed.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a continuation synchronized on a fail-over lock and condition.
+ * <tr><td> Automatically retry the continuation accross fail-overs until it succeeds, or raises an exception.
+ * </table>
+ *
+ * @todo Another continuation. Could use an interface Continuation (as described in other todos, for example, see
+ * {@link org.apache.qpid.pool.Job}). Then have a wrapping continuation (this), which blocks on an arbitrary
+ * Condition or Latch (specified in constructor call), that this blocks on before calling the wrapped Continuation.
+ * Must work on Java 1.4, so check retrotranslator works on Lock/Condition or latch first. Argument and return type
+ * to match wrapped condition as type parameters. Rename to AsyncConditionalContinuation or something like that.
+ *
+ * @todo InterruptedException not handled well.
+ */
+public class FailoverRetrySupport<T, E extends Exception> implements FailoverSupport<T, E>
+{
+ /** Used for debugging. */
+ private static final Logger _log = LoggerFactory.getLogger(FailoverRetrySupport.class);
+
+ /** The protected operation that is to be retried in the event of fail-over. */
+ FailoverProtectedOperation<T, E> operation;
+
+ /** The connection on which the fail-over protected operation is to be performed. */
+ AMQConnection connection;
+
+ /**
+ * Creates an automatic retrying fail-over handler for the specified operation.
+ *
+ * @param operation The fail-over protected operation to wrap in this handler.
+ */
+ public FailoverRetrySupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
+ {
+ this.operation = operation;
+ this.connection = con;
+ }
+
+ /**
+ * Delays a continuation until the "not failing over" condition is met on the specified connection. Repeats
+ * until the operation throws AMQException or succeeds without being interrupted by fail-over.
+ *
+ * @return The result of executing the continuation.
+ *
+ * @throws E Any underlying exception is allowed to fall through.
+ */
+ public T execute() throws E
+ {
+ while (true)
+ {
+ try
+ {
+ connection.blockUntilNotFailingOver();
+ }
+ catch (InterruptedException e)
+ {
+ _log.debug("Interrupted: " + e, e);
+
+ return null;
+ }
+
+ synchronized (connection.getFailoverMutex())
+ {
+ try
+ {
+ return operation.execute();
+ }
+ catch (FailoverException e)
+ {
+ _log.debug("Failover exception caught during operation: " + e, e);
+ }
+ catch (IllegalStateException e)
+ {
+ if (!(e.getMessage().startsWith("Fail-over interupted no-op failover support")))
+ {
+ throw e;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
index a150d1446a..5bd36aa88b 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/AccessRequestOkMethodHandler.java
@@ -1,36 +1,36 @@
-package org.apache.qpid.client.handler;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.client.state.StateAwareMethodListener;
-import org.apache.qpid.client.state.AMQStateManager;
-import org.apache.qpid.client.protocol.AMQProtocolSession;
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQInvalidRoutingKeyException;
-import org.apache.qpid.AMQChannelClosedException;
-import org.apache.qpid.protocol.AMQConstant;
-
-public class AccessRequestOkMethodHandler implements StateAwareMethodListener<AccessRequestOkBody>
-{
- private static final Logger _logger = LoggerFactory.getLogger(AccessRequestOkMethodHandler.class);
-
- private static AccessRequestOkMethodHandler _handler = new AccessRequestOkMethodHandler();
-
- public static AccessRequestOkMethodHandler getInstance()
- {
- return _handler;
- }
-
- public void methodReceived(AMQStateManager stateManager, AccessRequestOkBody method, int channelId)
- throws AMQException
- {
- _logger.debug("AccessRequestOk method received");
- final AMQProtocolSession session = stateManager.getProtocolSession();
- session.setTicket(method.getTicket(), channelId);
-
- }
-}
+package org.apache.qpid.client.handler;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.client.state.StateAwareMethodListener;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+import org.apache.qpid.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQInvalidRoutingKeyException;
+import org.apache.qpid.AMQChannelClosedException;
+import org.apache.qpid.protocol.AMQConstant;
+
+public class AccessRequestOkMethodHandler implements StateAwareMethodListener<AccessRequestOkBody>
+{
+ private static final Logger _logger = LoggerFactory.getLogger(AccessRequestOkMethodHandler.class);
+
+ private static AccessRequestOkMethodHandler _handler = new AccessRequestOkMethodHandler();
+
+ public static AccessRequestOkMethodHandler getInstance()
+ {
+ return _handler;
+ }
+
+ public void methodReceived(AMQStateManager stateManager, AccessRequestOkBody method, int channelId)
+ throws AMQException
+ {
+ _logger.debug("AccessRequestOk method received");
+ final AMQProtocolSession session = stateManager.getProtocolSession();
+ session.setTicket(method.getTicket(), channelId);
+
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
index de976b05bd..afb7517a12 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl.java
@@ -1,528 +1,528 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.handler;
-
-import java.util.Map;
-import java.util.HashMap;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.state.AMQStateManager;
-import org.apache.qpid.client.state.AMQMethodNotImplementedException;
-
-
-public class ClientMethodDispatcherImpl implements MethodDispatcher
-{
-
-
- private static final BasicCancelOkMethodHandler _basicCancelOkMethodHandler = BasicCancelOkMethodHandler.getInstance();
- private static final BasicDeliverMethodHandler _basicDeliverMethodHandler = BasicDeliverMethodHandler.getInstance();
- private static final BasicReturnMethodHandler _basicReturnMethodHandler = BasicReturnMethodHandler.getInstance();
- private static final ChannelCloseMethodHandler _channelCloseMethodHandler = ChannelCloseMethodHandler.getInstance();
- private static final ChannelFlowOkMethodHandler _channelFlowOkMethodHandler = ChannelFlowOkMethodHandler.getInstance();
- private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
- private static final ConnectionOpenOkMethodHandler _connectionOpenOkMethodHandler = ConnectionOpenOkMethodHandler.getInstance();
- private static final ConnectionRedirectMethodHandler _connectionRedirectMethodHandler = ConnectionRedirectMethodHandler.getInstance();
- private static final ConnectionSecureMethodHandler _connectionSecureMethodHandler = ConnectionSecureMethodHandler.getInstance();
- private static final ConnectionStartMethodHandler _connectionStartMethodHandler = ConnectionStartMethodHandler.getInstance();
- private static final ConnectionTuneMethodHandler _connectionTuneMethodHandler = ConnectionTuneMethodHandler.getInstance();
- private static final ExchangeBoundOkMethodHandler _exchangeBoundOkMethodHandler = ExchangeBoundOkMethodHandler.getInstance();
- private static final QueueDeleteOkMethodHandler _queueDeleteOkMethodHandler = QueueDeleteOkMethodHandler.getInstance();
-
-
-
- private static interface DispatcherFactory
- {
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager);
- }
-
- private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
- new HashMap<ProtocolVersion, DispatcherFactory>();
-
- static
- {
- _dispatcherFactories.put(ProtocolVersion.v8_0,
- new DispatcherFactory()
- {
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ClientMethodDispatcherImpl_8_0(stateManager);
- }
- });
-
- _dispatcherFactories.put(ProtocolVersion.v0_9,
- new DispatcherFactory()
- {
- public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
- {
- return new ClientMethodDispatcherImpl_0_9(stateManager);
- }
- });
-
- }
-
-
- public static ClientMethodDispatcherImpl newMethodDispatcher(ProtocolVersion version, AMQStateManager stateManager)
- {
- DispatcherFactory factory = _dispatcherFactories.get(version);
- return factory.createMethodDispatcher(stateManager);
- }
-
-
-
-
- private AMQStateManager _stateManager;
-
- public ClientMethodDispatcherImpl(AMQStateManager stateManager)
- {
- _stateManager = stateManager;
- }
-
-
- public AMQStateManager getStateManager()
- {
- return _stateManager;
- }
-
- public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
- {
- _basicCancelOkMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
- {
- _basicDeliverMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
- {
- _basicReturnMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
- {
- _channelCloseMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
- {
- _channelFlowOkMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- 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
- {
- return false;
- }
-
- public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
- {
- _connectionOpenOkMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
- {
- _connectionRedirectMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
- {
- _connectionSecureMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
- {
- _connectionStartMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
- {
- _connectionTuneMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
- {
- _queueDeleteOkMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
- {
- _exchangeBoundOkMethodHandler.methodReceived(_stateManager,body,channelId);
- return true;
- }
-
- public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.handler;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.AMQMethodNotImplementedException;
+
+
+public class ClientMethodDispatcherImpl implements MethodDispatcher
+{
+
+
+ private static final BasicCancelOkMethodHandler _basicCancelOkMethodHandler = BasicCancelOkMethodHandler.getInstance();
+ private static final BasicDeliverMethodHandler _basicDeliverMethodHandler = BasicDeliverMethodHandler.getInstance();
+ private static final BasicReturnMethodHandler _basicReturnMethodHandler = BasicReturnMethodHandler.getInstance();
+ private static final ChannelCloseMethodHandler _channelCloseMethodHandler = ChannelCloseMethodHandler.getInstance();
+ private static final ChannelFlowOkMethodHandler _channelFlowOkMethodHandler = ChannelFlowOkMethodHandler.getInstance();
+ private static final ConnectionCloseMethodHandler _connectionCloseMethodHandler = ConnectionCloseMethodHandler.getInstance();
+ private static final ConnectionOpenOkMethodHandler _connectionOpenOkMethodHandler = ConnectionOpenOkMethodHandler.getInstance();
+ private static final ConnectionRedirectMethodHandler _connectionRedirectMethodHandler = ConnectionRedirectMethodHandler.getInstance();
+ private static final ConnectionSecureMethodHandler _connectionSecureMethodHandler = ConnectionSecureMethodHandler.getInstance();
+ private static final ConnectionStartMethodHandler _connectionStartMethodHandler = ConnectionStartMethodHandler.getInstance();
+ private static final ConnectionTuneMethodHandler _connectionTuneMethodHandler = ConnectionTuneMethodHandler.getInstance();
+ private static final ExchangeBoundOkMethodHandler _exchangeBoundOkMethodHandler = ExchangeBoundOkMethodHandler.getInstance();
+ private static final QueueDeleteOkMethodHandler _queueDeleteOkMethodHandler = QueueDeleteOkMethodHandler.getInstance();
+
+
+
+ private static interface DispatcherFactory
+ {
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager);
+ }
+
+ private static final Map<ProtocolVersion, DispatcherFactory> _dispatcherFactories =
+ new HashMap<ProtocolVersion, DispatcherFactory>();
+
+ static
+ {
+ _dispatcherFactories.put(ProtocolVersion.v8_0,
+ new DispatcherFactory()
+ {
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ClientMethodDispatcherImpl_8_0(stateManager);
+ }
+ });
+
+ _dispatcherFactories.put(ProtocolVersion.v0_9,
+ new DispatcherFactory()
+ {
+ public ClientMethodDispatcherImpl createMethodDispatcher(AMQStateManager stateManager)
+ {
+ return new ClientMethodDispatcherImpl_0_9(stateManager);
+ }
+ });
+
+ }
+
+
+ public static ClientMethodDispatcherImpl newMethodDispatcher(ProtocolVersion version, AMQStateManager stateManager)
+ {
+ DispatcherFactory factory = _dispatcherFactories.get(version);
+ return factory.createMethodDispatcher(stateManager);
+ }
+
+
+
+
+ private AMQStateManager _stateManager;
+
+ public ClientMethodDispatcherImpl(AMQStateManager stateManager)
+ {
+ _stateManager = stateManager;
+ }
+
+
+ public AMQStateManager getStateManager()
+ {
+ return _stateManager;
+ }
+
+ public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
+ {
+ _basicCancelOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
+ {
+ _basicDeliverMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
+ {
+ _basicReturnMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
+ {
+ _channelCloseMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
+ {
+ _channelFlowOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ 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
+ {
+ return false;
+ }
+
+ public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
+ {
+ _connectionOpenOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
+ {
+ _connectionRedirectMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
+ {
+ _connectionSecureMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
+ {
+ _connectionStartMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
+ {
+ _connectionTuneMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
+ {
+ _queueDeleteOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamCancelOk(StreamCancelOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamConsumeOk(StreamConsumeOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchDtxSelect(DtxSelectBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchDtxStart(DtxStartBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileAck(FileAckBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileCancel(FileCancelBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileConsume(FileConsumeBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFilePublish(FilePublishBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileQos(FileQosBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileReject(FileRejectBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamCancel(StreamCancelBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamConsume(StreamConsumeBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamPublish(StreamPublishBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamQos(StreamQosBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchTunnelRequest(TunnelRequestBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchTxCommit(TxCommitBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchTxRollback(TxRollbackBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchDtxSelectOk(DtxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchDtxStartOk(DtxStartOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
+ {
+ _exchangeBoundOkMethodHandler.methodReceived(_stateManager,body,channelId);
+ return true;
+ }
+
+ public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchFileCancelOk(FileCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileConsumeOk(FileConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileDeliver(FileDeliverBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileOpen(FileOpenBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileOpenOk(FileOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileQosOk(FileQosOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileReturn(FileReturnBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchFileStage(FileStageBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchStreamDeliver(StreamDeliverBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamQosOk(StreamQosOkBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchStreamReturn(StreamReturnBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
index ae6d5e8283..e235368357 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_0_9.java
@@ -1,155 +1,155 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.handler;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.state.AMQStateManager;
-import org.apache.qpid.client.state.AMQMethodNotImplementedException;
-
-
-public class ClientMethodDispatcherImpl_0_9 extends ClientMethodDispatcherImpl implements MethodDispatcher_0_9
-{
- public ClientMethodDispatcherImpl_0_9(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
-
- public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(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
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- 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
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- 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
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- 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 dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
- {
- throw new AMQMethodNotImplementedException(body);
- }
-
- public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.handler;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.AMQMethodNotImplementedException;
+
+
+public class ClientMethodDispatcherImpl_0_9 extends ClientMethodDispatcherImpl implements MethodDispatcher_0_9
+{
+ public ClientMethodDispatcherImpl_0_9(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+
+ public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(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
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchMessageAppend(MessageAppendBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageCancel(MessageCancelBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ 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
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchMessageEmpty(MessageEmptyBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchMessageGet(MessageGetBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ 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
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchMessageRecover(MessageRecoverBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ 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 dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
+ {
+ throw new AMQMethodNotImplementedException(body);
+ }
+
+ public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
index 6bd6874cde..b0f003cd2d 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ClientMethodDispatcherImpl_8_0.java
@@ -1,85 +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.client.handler;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.state.AMQStateManager;
-
-public class ClientMethodDispatcherImpl_8_0 extends ClientMethodDispatcherImpl implements MethodDispatcher_8_0
-{
- public ClientMethodDispatcherImpl_8_0(AMQStateManager stateManager)
- {
- super(stateManager);
- }
-
- public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestContent(TestContentBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestContentOk(TestContentOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestInteger(TestIntegerBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestIntegerOk(TestIntegerOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestString(TestStringBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestStringOk(TestStringOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTable(TestTableBody body, int channelId) throws AMQException
- {
- return false;
- }
-
- public boolean dispatchTestTableOk(TestTableOkBody body, int channelId) throws AMQException
- {
- return false;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+ package org.apache.qpid.client.handler;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.state.AMQStateManager;
+
+public class ClientMethodDispatcherImpl_8_0 extends ClientMethodDispatcherImpl implements MethodDispatcher_8_0
+{
+ public ClientMethodDispatcherImpl_8_0(AMQStateManager stateManager)
+ {
+ super(stateManager);
+ }
+
+ public boolean dispatchBasicRecoverOk(BasicRecoverOkBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ public boolean dispatchChannelAlert(ChannelAlertBody body, int channelId) throws AMQException
+ {
+ return false;
+ }
+
+ 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/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
index 5904131122..9bdde01bf3 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesTypedMessage.java
@@ -1,802 +1,802 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-
-package org.apache.qpid.client.message;
-
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-
-import javax.jms.JMSException;
-import javax.jms.MessageEOFException;
-import javax.jms.MessageFormatException;
-import javax.jms.MessageNotReadableException;
-import javax.jms.MessageNotWriteableException;
-
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-
-/**
- * @author Apache Software Foundation
- */
-public abstract class AbstractBytesTypedMessage extends AbstractBytesMessage
-{
-
- protected static final byte BOOLEAN_TYPE = (byte) 1;
-
- protected static final byte BYTE_TYPE = (byte) 2;
-
- protected static final byte BYTEARRAY_TYPE = (byte) 3;
-
- protected static final byte SHORT_TYPE = (byte) 4;
-
- protected static final byte CHAR_TYPE = (byte) 5;
-
- protected static final byte INT_TYPE = (byte) 6;
-
- protected static final byte LONG_TYPE = (byte) 7;
-
- protected static final byte FLOAT_TYPE = (byte) 8;
-
- protected static final byte DOUBLE_TYPE = (byte) 9;
-
- protected static final byte STRING_TYPE = (byte) 10;
-
- protected static final byte NULL_STRING_TYPE = (byte) 11;
-
- /**
- * This is set when reading a byte array. The readBytes(byte[]) method supports multiple calls to read
- * a byte array in multiple chunks, hence this is used to track how much is left to be read
- */
- private int _byteArrayRemaining = -1;
-
- AbstractBytesTypedMessage()
- {
- this(null);
- }
-
- /**
- * Construct a stream message with existing data.
- *
- * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
- * set to auto expand
- */
- AbstractBytesTypedMessage(ByteBuffer data)
- {
- super(data); // this instanties a content header
- }
-
-
- AbstractBytesTypedMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
- {
- super(messageNbr, contentHeader, exchange, routingKey, data);
- }
-
-
- protected byte readWireType() throws MessageFormatException, MessageEOFException,
- MessageNotReadableException
- {
- checkReadable();
- checkAvailable(1);
- return _data.get();
- }
-
- protected void writeTypeDiscriminator(byte type) throws MessageNotWriteableException
- {
- checkWritable();
- _data.put(type);
- _changedData = true;
- }
-
- protected boolean readBoolean() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- boolean result;
- try
- {
- switch (wireType)
- {
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = readBooleanImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Boolean.parseBoolean(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a boolean");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- private boolean readBooleanImpl()
- {
- return _data.get() != 0;
- }
-
- protected byte readByte() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- byte result;
- try
- {
- switch (wireType)
- {
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Byte.parseByte(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a byte");
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- return result;
- }
-
- private byte readByteImpl()
- {
- return _data.get();
- }
-
- protected short readShort() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- short result;
- try
- {
- switch (wireType)
- {
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Short.parseShort(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a short");
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- return result;
- }
-
- private short readShortImpl()
- {
- return _data.getShort();
- }
-
- /**
- * Note that this method reads a unicode character as two bytes from the stream
- *
- * @return the character read from the stream
- * @throws javax.jms.JMSException
- */
- protected char readChar() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- try
- {
- if(wireType == NULL_STRING_TYPE){
- throw new NullPointerException();
- }
-
- if (wireType != CHAR_TYPE)
- {
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a char");
- }
- else
- {
- checkAvailable(2);
- return readCharImpl();
- }
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- private char readCharImpl()
- {
- return _data.getChar();
- }
-
- protected int readInt() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- int result;
- try
- {
- switch (wireType)
- {
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Integer.parseInt(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to an int");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- protected int readIntImpl()
- {
- return _data.getInt();
- }
-
- protected long readLong() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- long result;
- try
- {
- switch (wireType)
- {
- case LONG_TYPE:
- checkAvailable(8);
- result = readLongImpl();
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Long.parseLong(readStringImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a long");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- private long readLongImpl()
- {
- return _data.getLong();
- }
-
- protected float readFloat() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- float result;
- try
- {
- switch (wireType)
- {
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Float.parseFloat(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a float");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- private float readFloatImpl()
- {
- return _data.getFloat();
- }
-
- protected double readDouble() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- double result;
- try
- {
- switch (wireType)
- {
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = readDoubleImpl();
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = Double.parseDouble(readStringImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a double");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- private double readDoubleImpl()
- {
- return _data.getDouble();
- }
-
- protected String readString() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- String result;
- try
- {
- switch (wireType)
- {
- case STRING_TYPE:
- checkAvailable(1);
- result = readStringImpl();
- break;
- case NULL_STRING_TYPE:
- result = null;
- throw new NullPointerException("data is null");
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = String.valueOf(readBooleanImpl());
- break;
- case LONG_TYPE:
- checkAvailable(8);
- result = String.valueOf(readLongImpl());
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = String.valueOf(readIntImpl());
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = String.valueOf(readShortImpl());
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = String.valueOf(readByteImpl());
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = String.valueOf(readFloatImpl());
- break;
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = String.valueOf(readDoubleImpl());
- break;
- case CHAR_TYPE:
- checkAvailable(2);
- result = String.valueOf(readCharImpl());
- break;
- default:
- _data.position(position);
- throw new MessageFormatException("Unable to convert " + wireType + " to a String");
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- protected String readStringImpl() throws JMSException
- {
- try
- {
- return _data.getString(Charset.forName("UTF-8").newDecoder());
- }
- catch (CharacterCodingException e)
- {
- JMSException je = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
- je.setLinkedException(e);
- throw je;
- }
- }
-
- protected int readBytes(byte[] bytes) throws JMSException
- {
- if (bytes == null)
- {
- throw new IllegalArgumentException("byte array must not be null");
- }
- checkReadable();
- // first call
- if (_byteArrayRemaining == -1)
- {
- // type discriminator checked separately so you get a MessageFormatException rather than
- // an EOF even in the case where both would be applicable
- checkAvailable(1);
- byte wireType = readWireType();
- if (wireType != BYTEARRAY_TYPE)
- {
- throw new MessageFormatException("Unable to convert " + wireType + " to a byte array");
- }
- checkAvailable(4);
- int size = _data.getInt();
- // length of -1 indicates null
- if (size == -1)
- {
- return -1;
- }
- else
- {
- if (size > _data.remaining())
- {
- throw new MessageEOFException("Byte array has stated length " + size + " but message only contains " +
- _data.remaining() + " bytes");
- }
- else
- {
- _byteArrayRemaining = size;
- }
- }
- }
- else if (_byteArrayRemaining == 0)
- {
- _byteArrayRemaining = -1;
- return -1;
- }
-
- int returnedSize = readBytesImpl(bytes);
- if (returnedSize < bytes.length)
- {
- _byteArrayRemaining = -1;
- }
- return returnedSize;
- }
-
- private int readBytesImpl(byte[] bytes)
- {
- int count = (_byteArrayRemaining >= bytes.length ? bytes.length : _byteArrayRemaining);
- _byteArrayRemaining -= count;
-
- if (count == 0)
- {
- return 0;
- }
- else
- {
- _data.get(bytes, 0, count);
- return count;
- }
- }
-
- protected Object readObject() throws JMSException
- {
- int position = _data.position();
- byte wireType = readWireType();
- Object result = null;
- try
- {
- switch (wireType)
- {
- case BOOLEAN_TYPE:
- checkAvailable(1);
- result = readBooleanImpl();
- break;
- case BYTE_TYPE:
- checkAvailable(1);
- result = readByteImpl();
- break;
- case BYTEARRAY_TYPE:
- checkAvailable(4);
- int size = _data.getInt();
- if (size == -1)
- {
- result = null;
- }
- else
- {
- _byteArrayRemaining = size;
- byte[] bytesResult = new byte[size];
- readBytesImpl(bytesResult);
- result = bytesResult;
- }
- break;
- case SHORT_TYPE:
- checkAvailable(2);
- result = readShortImpl();
- break;
- case CHAR_TYPE:
- checkAvailable(2);
- result = readCharImpl();
- break;
- case INT_TYPE:
- checkAvailable(4);
- result = readIntImpl();
- break;
- case LONG_TYPE:
- checkAvailable(8);
- result = readLongImpl();
- break;
- case FLOAT_TYPE:
- checkAvailable(4);
- result = readFloatImpl();
- break;
- case DOUBLE_TYPE:
- checkAvailable(8);
- result = readDoubleImpl();
- break;
- case NULL_STRING_TYPE:
- result = null;
- break;
- case STRING_TYPE:
- checkAvailable(1);
- result = readStringImpl();
- break;
- }
- return result;
- }
- catch (RuntimeException e)
- {
- _data.position(position);
- throw e;
- }
- }
-
- protected void writeBoolean(boolean b) throws JMSException
- {
- writeTypeDiscriminator(BOOLEAN_TYPE);
- _data.put(b ? (byte) 1 : (byte) 0);
- }
-
- protected void writeByte(byte b) throws JMSException
- {
- writeTypeDiscriminator(BYTE_TYPE);
- _data.put(b);
- }
-
- protected void writeShort(short i) throws JMSException
- {
- writeTypeDiscriminator(SHORT_TYPE);
- _data.putShort(i);
- }
-
- protected void writeChar(char c) throws JMSException
- {
- writeTypeDiscriminator(CHAR_TYPE);
- _data.putChar(c);
- }
-
- protected void writeInt(int i) throws JMSException
- {
- writeTypeDiscriminator(INT_TYPE);
- writeIntImpl(i);
- }
-
- protected void writeIntImpl(int i)
- {
- _data.putInt(i);
- }
-
- protected void writeLong(long l) throws JMSException
- {
- writeTypeDiscriminator(LONG_TYPE);
- _data.putLong(l);
- }
-
- protected void writeFloat(float v) throws JMSException
- {
- writeTypeDiscriminator(FLOAT_TYPE);
- _data.putFloat(v);
- }
-
- protected void writeDouble(double v) throws JMSException
- {
- writeTypeDiscriminator(DOUBLE_TYPE);
- _data.putDouble(v);
- }
-
- protected void writeString(String string) throws JMSException
- {
- if (string == null)
- {
- writeTypeDiscriminator(NULL_STRING_TYPE);
- }
- else
- {
- writeTypeDiscriminator(STRING_TYPE);
- try
- {
- writeStringImpl(string);
- }
- catch (CharacterCodingException e)
- {
- JMSException ex = new JMSException("Unable to encode string: " + e);
- ex.setLinkedException(e);
- throw ex;
- }
- }
- }
-
- protected void writeStringImpl(String string)
- throws CharacterCodingException
- {
- _data.putString(string, Charset.forName("UTF-8").newEncoder());
- // we must write the null terminator ourselves
- _data.put((byte) 0);
- }
-
- protected void writeBytes(byte[] bytes) throws JMSException
- {
- writeBytes(bytes, 0, bytes == null ? 0 : bytes.length);
- }
-
- protected void writeBytes(byte[] bytes, int offset, int length) throws JMSException
- {
- writeTypeDiscriminator(BYTEARRAY_TYPE);
- if (bytes == null)
- {
- _data.putInt(-1);
- }
- else
- {
- _data.putInt(length);
- _data.put(bytes, offset, length);
- }
- }
-
- protected void writeObject(Object object) throws JMSException
- {
- checkWritable();
- Class clazz;
-
- if (object == null)
- {
- // string handles the output of null values
- clazz = String.class;
- }
- else
- {
- clazz = object.getClass();
- }
-
- if (clazz == Byte.class)
- {
- writeByte((Byte) object);
- }
- else if (clazz == Boolean.class)
- {
- writeBoolean((Boolean) object);
- }
- else if (clazz == byte[].class)
- {
- writeBytes((byte[]) object);
- }
- else if (clazz == Short.class)
- {
- writeShort((Short) object);
- }
- else if (clazz == Character.class)
- {
- writeChar((Character) object);
- }
- else if (clazz == Integer.class)
- {
- writeInt((Integer) object);
- }
- else if (clazz == Long.class)
- {
- writeLong((Long) object);
- }
- else if (clazz == Float.class)
- {
- writeFloat((Float) object);
- }
- else if (clazz == Double.class)
- {
- writeDouble((Double) object);
- }
- else if (clazz == String.class)
- {
- writeString((String) object);
- }
- else
- {
- throw new MessageFormatException("Only primitives plus byte arrays and String are valid types");
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+package org.apache.qpid.client.message;
+
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+import javax.jms.JMSException;
+import javax.jms.MessageEOFException;
+import javax.jms.MessageFormatException;
+import javax.jms.MessageNotReadableException;
+import javax.jms.MessageNotWriteableException;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+
+/**
+ * @author Apache Software Foundation
+ */
+public abstract class AbstractBytesTypedMessage extends AbstractBytesMessage
+{
+
+ protected static final byte BOOLEAN_TYPE = (byte) 1;
+
+ protected static final byte BYTE_TYPE = (byte) 2;
+
+ protected static final byte BYTEARRAY_TYPE = (byte) 3;
+
+ protected static final byte SHORT_TYPE = (byte) 4;
+
+ protected static final byte CHAR_TYPE = (byte) 5;
+
+ protected static final byte INT_TYPE = (byte) 6;
+
+ protected static final byte LONG_TYPE = (byte) 7;
+
+ protected static final byte FLOAT_TYPE = (byte) 8;
+
+ protected static final byte DOUBLE_TYPE = (byte) 9;
+
+ protected static final byte STRING_TYPE = (byte) 10;
+
+ protected static final byte NULL_STRING_TYPE = (byte) 11;
+
+ /**
+ * This is set when reading a byte array. The readBytes(byte[]) method supports multiple calls to read
+ * a byte array in multiple chunks, hence this is used to track how much is left to be read
+ */
+ private int _byteArrayRemaining = -1;
+
+ AbstractBytesTypedMessage()
+ {
+ this(null);
+ }
+
+ /**
+ * Construct a stream message with existing data.
+ *
+ * @param data the data that comprises this message. If data is null, you get a 1024 byte buffer that is
+ * set to auto expand
+ */
+ AbstractBytesTypedMessage(ByteBuffer data)
+ {
+ super(data); // this instanties a content header
+ }
+
+
+ AbstractBytesTypedMessage(long messageNbr, BasicContentHeaderProperties contentHeader, AMQShortString exchange,
+ AMQShortString routingKey, ByteBuffer data) throws AMQException
+ {
+ super(messageNbr, contentHeader, exchange, routingKey, data);
+ }
+
+
+ protected byte readWireType() throws MessageFormatException, MessageEOFException,
+ MessageNotReadableException
+ {
+ checkReadable();
+ checkAvailable(1);
+ return _data.get();
+ }
+
+ protected void writeTypeDiscriminator(byte type) throws MessageNotWriteableException
+ {
+ checkWritable();
+ _data.put(type);
+ _changedData = true;
+ }
+
+ protected boolean readBoolean() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ boolean result;
+ try
+ {
+ switch (wireType)
+ {
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = readBooleanImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Boolean.parseBoolean(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a boolean");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private boolean readBooleanImpl()
+ {
+ return _data.get() != 0;
+ }
+
+ protected byte readByte() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ byte result;
+ try
+ {
+ switch (wireType)
+ {
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Byte.parseByte(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a byte");
+ }
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ return result;
+ }
+
+ private byte readByteImpl()
+ {
+ return _data.get();
+ }
+
+ protected short readShort() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ short result;
+ try
+ {
+ switch (wireType)
+ {
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Short.parseShort(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a short");
+ }
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ return result;
+ }
+
+ private short readShortImpl()
+ {
+ return _data.getShort();
+ }
+
+ /**
+ * Note that this method reads a unicode character as two bytes from the stream
+ *
+ * @return the character read from the stream
+ * @throws javax.jms.JMSException
+ */
+ protected char readChar() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ try
+ {
+ if(wireType == NULL_STRING_TYPE){
+ throw new NullPointerException();
+ }
+
+ if (wireType != CHAR_TYPE)
+ {
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a char");
+ }
+ else
+ {
+ checkAvailable(2);
+ return readCharImpl();
+ }
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private char readCharImpl()
+ {
+ return _data.getChar();
+ }
+
+ protected int readInt() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ int result;
+ try
+ {
+ switch (wireType)
+ {
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Integer.parseInt(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to an int");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected int readIntImpl()
+ {
+ return _data.getInt();
+ }
+
+ protected long readLong() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ long result;
+ try
+ {
+ switch (wireType)
+ {
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = readLongImpl();
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Long.parseLong(readStringImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a long");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private long readLongImpl()
+ {
+ return _data.getLong();
+ }
+
+ protected float readFloat() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ float result;
+ try
+ {
+ switch (wireType)
+ {
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Float.parseFloat(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a float");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private float readFloatImpl()
+ {
+ return _data.getFloat();
+ }
+
+ protected double readDouble() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ double result;
+ try
+ {
+ switch (wireType)
+ {
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = readDoubleImpl();
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = Double.parseDouble(readStringImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a double");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ private double readDoubleImpl()
+ {
+ return _data.getDouble();
+ }
+
+ protected String readString() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ String result;
+ try
+ {
+ switch (wireType)
+ {
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = readStringImpl();
+ break;
+ case NULL_STRING_TYPE:
+ result = null;
+ throw new NullPointerException("data is null");
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = String.valueOf(readBooleanImpl());
+ break;
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = String.valueOf(readLongImpl());
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = String.valueOf(readIntImpl());
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = String.valueOf(readShortImpl());
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = String.valueOf(readByteImpl());
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = String.valueOf(readFloatImpl());
+ break;
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = String.valueOf(readDoubleImpl());
+ break;
+ case CHAR_TYPE:
+ checkAvailable(2);
+ result = String.valueOf(readCharImpl());
+ break;
+ default:
+ _data.position(position);
+ throw new MessageFormatException("Unable to convert " + wireType + " to a String");
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected String readStringImpl() throws JMSException
+ {
+ try
+ {
+ return _data.getString(Charset.forName("UTF-8").newDecoder());
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException je = new JMSException("Error decoding byte stream as a UTF8 string: " + e);
+ je.setLinkedException(e);
+ throw je;
+ }
+ }
+
+ protected int readBytes(byte[] bytes) throws JMSException
+ {
+ if (bytes == null)
+ {
+ throw new IllegalArgumentException("byte array must not be null");
+ }
+ checkReadable();
+ // first call
+ if (_byteArrayRemaining == -1)
+ {
+ // type discriminator checked separately so you get a MessageFormatException rather than
+ // an EOF even in the case where both would be applicable
+ checkAvailable(1);
+ byte wireType = readWireType();
+ if (wireType != BYTEARRAY_TYPE)
+ {
+ throw new MessageFormatException("Unable to convert " + wireType + " to a byte array");
+ }
+ checkAvailable(4);
+ int size = _data.getInt();
+ // length of -1 indicates null
+ if (size == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ if (size > _data.remaining())
+ {
+ throw new MessageEOFException("Byte array has stated length " + size + " but message only contains " +
+ _data.remaining() + " bytes");
+ }
+ else
+ {
+ _byteArrayRemaining = size;
+ }
+ }
+ }
+ else if (_byteArrayRemaining == 0)
+ {
+ _byteArrayRemaining = -1;
+ return -1;
+ }
+
+ int returnedSize = readBytesImpl(bytes);
+ if (returnedSize < bytes.length)
+ {
+ _byteArrayRemaining = -1;
+ }
+ return returnedSize;
+ }
+
+ private int readBytesImpl(byte[] bytes)
+ {
+ int count = (_byteArrayRemaining >= bytes.length ? bytes.length : _byteArrayRemaining);
+ _byteArrayRemaining -= count;
+
+ if (count == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ _data.get(bytes, 0, count);
+ return count;
+ }
+ }
+
+ protected Object readObject() throws JMSException
+ {
+ int position = _data.position();
+ byte wireType = readWireType();
+ Object result = null;
+ try
+ {
+ switch (wireType)
+ {
+ case BOOLEAN_TYPE:
+ checkAvailable(1);
+ result = readBooleanImpl();
+ break;
+ case BYTE_TYPE:
+ checkAvailable(1);
+ result = readByteImpl();
+ break;
+ case BYTEARRAY_TYPE:
+ checkAvailable(4);
+ int size = _data.getInt();
+ if (size == -1)
+ {
+ result = null;
+ }
+ else
+ {
+ _byteArrayRemaining = size;
+ byte[] bytesResult = new byte[size];
+ readBytesImpl(bytesResult);
+ result = bytesResult;
+ }
+ break;
+ case SHORT_TYPE:
+ checkAvailable(2);
+ result = readShortImpl();
+ break;
+ case CHAR_TYPE:
+ checkAvailable(2);
+ result = readCharImpl();
+ break;
+ case INT_TYPE:
+ checkAvailable(4);
+ result = readIntImpl();
+ break;
+ case LONG_TYPE:
+ checkAvailable(8);
+ result = readLongImpl();
+ break;
+ case FLOAT_TYPE:
+ checkAvailable(4);
+ result = readFloatImpl();
+ break;
+ case DOUBLE_TYPE:
+ checkAvailable(8);
+ result = readDoubleImpl();
+ break;
+ case NULL_STRING_TYPE:
+ result = null;
+ break;
+ case STRING_TYPE:
+ checkAvailable(1);
+ result = readStringImpl();
+ break;
+ }
+ return result;
+ }
+ catch (RuntimeException e)
+ {
+ _data.position(position);
+ throw e;
+ }
+ }
+
+ protected void writeBoolean(boolean b) throws JMSException
+ {
+ writeTypeDiscriminator(BOOLEAN_TYPE);
+ _data.put(b ? (byte) 1 : (byte) 0);
+ }
+
+ protected void writeByte(byte b) throws JMSException
+ {
+ writeTypeDiscriminator(BYTE_TYPE);
+ _data.put(b);
+ }
+
+ protected void writeShort(short i) throws JMSException
+ {
+ writeTypeDiscriminator(SHORT_TYPE);
+ _data.putShort(i);
+ }
+
+ protected void writeChar(char c) throws JMSException
+ {
+ writeTypeDiscriminator(CHAR_TYPE);
+ _data.putChar(c);
+ }
+
+ protected void writeInt(int i) throws JMSException
+ {
+ writeTypeDiscriminator(INT_TYPE);
+ writeIntImpl(i);
+ }
+
+ protected void writeIntImpl(int i)
+ {
+ _data.putInt(i);
+ }
+
+ protected void writeLong(long l) throws JMSException
+ {
+ writeTypeDiscriminator(LONG_TYPE);
+ _data.putLong(l);
+ }
+
+ protected void writeFloat(float v) throws JMSException
+ {
+ writeTypeDiscriminator(FLOAT_TYPE);
+ _data.putFloat(v);
+ }
+
+ protected void writeDouble(double v) throws JMSException
+ {
+ writeTypeDiscriminator(DOUBLE_TYPE);
+ _data.putDouble(v);
+ }
+
+ protected void writeString(String string) throws JMSException
+ {
+ if (string == null)
+ {
+ writeTypeDiscriminator(NULL_STRING_TYPE);
+ }
+ else
+ {
+ writeTypeDiscriminator(STRING_TYPE);
+ try
+ {
+ writeStringImpl(string);
+ }
+ catch (CharacterCodingException e)
+ {
+ JMSException ex = new JMSException("Unable to encode string: " + e);
+ ex.setLinkedException(e);
+ throw ex;
+ }
+ }
+ }
+
+ protected void writeStringImpl(String string)
+ throws CharacterCodingException
+ {
+ _data.putString(string, Charset.forName("UTF-8").newEncoder());
+ // we must write the null terminator ourselves
+ _data.put((byte) 0);
+ }
+
+ protected void writeBytes(byte[] bytes) throws JMSException
+ {
+ writeBytes(bytes, 0, bytes == null ? 0 : bytes.length);
+ }
+
+ protected void writeBytes(byte[] bytes, int offset, int length) throws JMSException
+ {
+ writeTypeDiscriminator(BYTEARRAY_TYPE);
+ if (bytes == null)
+ {
+ _data.putInt(-1);
+ }
+ else
+ {
+ _data.putInt(length);
+ _data.put(bytes, offset, length);
+ }
+ }
+
+ protected void writeObject(Object object) throws JMSException
+ {
+ checkWritable();
+ Class clazz;
+
+ if (object == null)
+ {
+ // string handles the output of null values
+ clazz = String.class;
+ }
+ else
+ {
+ clazz = object.getClass();
+ }
+
+ if (clazz == Byte.class)
+ {
+ writeByte((Byte) object);
+ }
+ else if (clazz == Boolean.class)
+ {
+ writeBoolean((Boolean) object);
+ }
+ else if (clazz == byte[].class)
+ {
+ writeBytes((byte[]) object);
+ }
+ else if (clazz == Short.class)
+ {
+ writeShort((Short) object);
+ }
+ else if (clazz == Character.class)
+ {
+ writeChar((Character) object);
+ }
+ else if (clazz == Integer.class)
+ {
+ writeInt((Integer) object);
+ }
+ else if (clazz == Long.class)
+ {
+ writeLong((Long) object);
+ }
+ else if (clazz == Float.class)
+ {
+ writeFloat((Float) object);
+ }
+ else if (clazz == Double.class)
+ {
+ writeDouble((Double) object);
+ }
+ else if (clazz == String.class)
+ {
+ writeString((String) object);
+ }
+ else
+ {
+ throw new MessageFormatException("Only primitives plus byte arrays and String are valid types");
+ }
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
index 39b4e1e27b..fec0117a03 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java
@@ -1,552 +1,552 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.message;
-
-import java.util.Enumeration;
-
-import javax.jms.JMSException;
-import javax.jms.MessageFormatException;
-
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.AMQPInvalidClassException;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-
-
-public final class JMSHeaderAdapter
-{
- private final FieldTable _headers;
-
- public JMSHeaderAdapter(FieldTable headers)
- {
- _headers = headers;
- }
-
-
- public FieldTable getHeaders()
- {
- return _headers;
- }
-
- public boolean getBoolean(String string) throws JMSException
- {
- checkPropertyName(string);
- Boolean b = getHeaders().getBoolean(string);
-
- if (b == null)
- {
- if (getHeaders().containsKey(string))
- {
- Object str = getHeaders().getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getBoolean can't use " + string + " item.");
- }
- else
- {
- return Boolean.valueOf((String) str);
- }
- }
- else
- {
- b = Boolean.valueOf(null);
- }
- }
-
- return b;
- }
-
- public boolean getBoolean(AMQShortString string) throws JMSException
- {
- checkPropertyName(string);
- Boolean b = getHeaders().getBoolean(string);
-
- if (b == null)
- {
- if (getHeaders().containsKey(string))
- {
- Object str = getHeaders().getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getBoolean can't use " + string + " item.");
- }
- else
- {
- return Boolean.valueOf((String) str);
- }
- }
- else
- {
- b = Boolean.valueOf(null);
- }
- }
-
- return b;
- }
-
- public char getCharacter(String string) throws JMSException
- {
- checkPropertyName(string);
- Character c = getHeaders().getCharacter(string);
-
- if (c == null)
- {
- if (getHeaders().isNullStringValue(string))
- {
- throw new NullPointerException("Cannot convert null char");
- }
- else
- {
- throw new MessageFormatException("getChar can't use " + string + " item.");
- }
- }
- else
- {
- return (char) c;
- }
- }
-
- public byte[] getBytes(String string) throws JMSException
- {
- return getBytes(new AMQShortString(string));
- }
-
- public byte[] getBytes(AMQShortString string) throws JMSException
- {
- checkPropertyName(string);
-
- byte[] bs = getHeaders().getBytes(string);
-
- if (bs == null)
- {
- throw new MessageFormatException("getBytes can't use " + string + " item.");
- }
- else
- {
- return bs;
- }
- }
-
- public byte getByte(String string) throws JMSException
- {
- checkPropertyName(string);
- Byte b = getHeaders().getByte(string);
- if (b == null)
- {
- if (getHeaders().containsKey(string))
- {
- Object str = getHeaders().getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getByte can't use " + string + " item.");
- }
- else
- {
- return Byte.valueOf((String) str);
- }
- }
- else
- {
- b = Byte.valueOf(null);
- }
- }
-
- return b;
- }
-
- public short getShort(String string) throws JMSException
- {
- checkPropertyName(string);
- Short s = getHeaders().getShort(string);
-
- if (s == null)
- {
- s = Short.valueOf(getByte(string));
- }
-
- return s;
- }
-
- public int getInteger(String string) throws JMSException
- {
- checkPropertyName(string);
- Integer i = getHeaders().getInteger(string);
-
- if (i == null)
- {
- i = Integer.valueOf(getShort(string));
- }
-
- return i;
- }
-
- public long getLong(String string) throws JMSException
- {
- checkPropertyName(string);
- Long l = getHeaders().getLong(string);
-
- if (l == null)
- {
- l = Long.valueOf(getInteger(string));
- }
-
- return l;
- }
-
- public float getFloat(String string) throws JMSException
- {
- checkPropertyName(string);
- Float f = getHeaders().getFloat(string);
-
- if (f == null)
- {
- if (getHeaders().containsKey(string))
- {
- Object str = getHeaders().getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getFloat can't use " + string + " item.");
- }
- else
- {
- return Float.valueOf((String) str);
- }
- }
- else
- {
- f = Float.valueOf(null);
- }
-
- }
-
- return f;
- }
-
- public double getDouble(String string) throws JMSException
- {
- checkPropertyName(string);
- Double d = getHeaders().getDouble(string);
-
- if (d == null)
- {
- d = Double.valueOf(getFloat(string));
- }
-
- return d;
- }
-
- public String getString(String string) throws JMSException
- {
- checkPropertyName(string);
- String s = getHeaders().getString(string);
-
- if (s == null)
- {
- if (getHeaders().containsKey(string))
- {
- Object o = getHeaders().getObject(string);
- if (o instanceof byte[])
- {
- throw new MessageFormatException("getObject couldn't find " + string + " item.");
- }
- else
- {
- if (o == null)
- {
- return null;
- }
- else
- {
- s = String.valueOf(o);
- }
- }
- }//else return s // null;
- }
-
- return s;
- }
-
- public Object getObject(String string) throws JMSException
- {
- checkPropertyName(string);
- return getHeaders().getObject(string);
- }
-
- public void setBoolean(AMQShortString string, boolean b) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setBoolean(string, b);
- }
-
- public void setBoolean(String string, boolean b) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setBoolean(string, b);
- }
-
- public void setChar(String string, char c) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setChar(string, c);
- }
-
- public Object setBytes(AMQShortString string, byte[] bytes)
- {
- checkPropertyName(string);
- return getHeaders().setBytes(string, bytes);
- }
-
- public Object setBytes(String string, byte[] bytes)
- {
- checkPropertyName(string);
- return getHeaders().setBytes(string, bytes);
- }
-
- public Object setBytes(String string, byte[] bytes, int start, int length)
- {
- checkPropertyName(string);
- return getHeaders().setBytes(string, bytes, start, length);
- }
-
- public void setByte(String string, byte b) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setByte(string, b);
- }
-
- public void setByte(AMQShortString string, byte b) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setByte(string, b);
- }
-
-
- public void setShort(String string, short i) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setShort(string, i);
- }
-
- public void setInteger(String string, int i) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setInteger(string, i);
- }
-
- public void setInteger(AMQShortString string, int i) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setInteger(string, i);
- }
-
- public void setLong(String string, long l) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setLong(string, l);
- }
-
- public void setFloat(String string, float v) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setFloat(string, v);
- }
-
- public void setDouble(String string, double v) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setDouble(string, v);
- }
-
- public void setString(String string, String string1) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setString(string, string1);
- }
-
- public void setString(AMQShortString string, String string1) throws JMSException
- {
- checkPropertyName(string);
- getHeaders().setString(string, string1);
- }
-
- public void setObject(String string, Object object) throws JMSException
- {
- checkPropertyName(string);
- try
- {
- getHeaders().setObject(string, object);
- }
- catch (AMQPInvalidClassException aice)
- {
- MessageFormatException mfe = new MessageFormatException("Only primatives are allowed object is:" + object.getClass());
- mfe.setLinkedException(aice);
- throw mfe;
- }
- }
-
- public boolean itemExists(String string) throws JMSException
- {
- checkPropertyName(string);
- return getHeaders().containsKey(string);
- }
-
- public Enumeration getPropertyNames()
- {
- return getHeaders().getPropertyNames();
- }
-
- public void clear()
- {
- getHeaders().clear();
- }
-
- public boolean propertyExists(AMQShortString propertyName)
- {
- checkPropertyName(propertyName);
- return getHeaders().propertyExists(propertyName);
- }
-
- public boolean propertyExists(String propertyName)
- {
- checkPropertyName(propertyName);
- return getHeaders().propertyExists(propertyName);
- }
-
- public Object put(Object key, Object value)
- {
- checkPropertyName(key.toString());
- return getHeaders().setObject(key.toString(), value);
- }
-
- public Object remove(AMQShortString propertyName)
- {
- checkPropertyName(propertyName);
- return getHeaders().remove(propertyName);
- }
-
- public Object remove(String propertyName)
- {
- checkPropertyName(propertyName);
- return getHeaders().remove(propertyName);
- }
-
- public boolean isEmpty()
- {
- return getHeaders().isEmpty();
- }
-
- public void writeToBuffer(ByteBuffer data)
- {
- getHeaders().writeToBuffer(data);
- }
-
- public Enumeration getMapNames()
- {
- return getPropertyNames();
- }
-
- protected static void checkPropertyName(CharSequence propertyName)
- {
- if (propertyName == null)
- {
- throw new IllegalArgumentException("Property name must not be null");
- }
- else if (propertyName.length() == 0)
- {
- throw new IllegalArgumentException("Property name must not be the empty string");
- }
-
- checkIdentiferFormat(propertyName);
- }
-
- protected static void checkIdentiferFormat(CharSequence propertyName)
- {
-// JMS requirements 3.5.1 Property Names
-// Identifiers:
-// - An identifier is an unlimited-length character sequence that must begin
-// with a Java identifier start character; all following characters must be Java
-// identifier part characters. An identifier start character is any character for
-// which the method Character.isJavaIdentifierStart returns true. This includes
-// '_' and '$'. An identifier part character is any character for which the
-// method Character.isJavaIdentifierPart returns true.
-// - Identifiers cannot be the names NULL, TRUE, or FALSE.
-// � Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
-// ESCAPE.
-// � Identifiers are either header field references or property references. The
-// type of a property value in a message selector corresponds to the type
-// used to set the property. If a property that does not exist in a message is
-// referenced, its value is NULL. The semantics of evaluating NULL values
-// in a selector are described in Section 3.8.1.2, �Null Values.�
-// � The conversions that apply to the get methods for properties do not
-// apply when a property is used in a message selector expression. For
-// example, suppose you set a property as a string value, as in the
-// following:
-// myMessage.setStringProperty("NumberOfOrders", "2");
-// The following expression in a message selector would evaluate to false,
-// because a string cannot be used in an arithmetic expression:
-// "NumberOfOrders > 1"
-// � Identifiers are case sensitive.
-// � Message header field references are restricted to JMSDeliveryMode,
-// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
-// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
-// null and if so are treated as a NULL value.
-
- if (Boolean.getBoolean("strict-jms"))
- {
- // JMS start character
- if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
- }
-
- // JMS part character
- int length = propertyName.length();
- for (int c = 1; c < length; c++)
- {
- if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
- }
- }
-
- // JMS invalid names
- if ((propertyName.equals("NULL")
- || propertyName.equals("TRUE")
- || propertyName.equals("FALSE")
- || propertyName.equals("NOT")
- || propertyName.equals("AND")
- || propertyName.equals("OR")
- || propertyName.equals("BETWEEN")
- || propertyName.equals("LIKE")
- || propertyName.equals("IN")
- || propertyName.equals("IS")
- || propertyName.equals("ESCAPE")))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
- }
- }
-
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.message;
+
+import java.util.Enumeration;
+
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQPInvalidClassException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+
+
+public final class JMSHeaderAdapter
+{
+ private final FieldTable _headers;
+
+ public JMSHeaderAdapter(FieldTable headers)
+ {
+ _headers = headers;
+ }
+
+
+ public FieldTable getHeaders()
+ {
+ return _headers;
+ }
+
+ public boolean getBoolean(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Boolean b = getHeaders().getBoolean(string);
+
+ if (b == null)
+ {
+ if (getHeaders().containsKey(string))
+ {
+ Object str = getHeaders().getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getBoolean can't use " + string + " item.");
+ }
+ else
+ {
+ return Boolean.valueOf((String) str);
+ }
+ }
+ else
+ {
+ b = Boolean.valueOf(null);
+ }
+ }
+
+ return b;
+ }
+
+ public boolean getBoolean(AMQShortString string) throws JMSException
+ {
+ checkPropertyName(string);
+ Boolean b = getHeaders().getBoolean(string);
+
+ if (b == null)
+ {
+ if (getHeaders().containsKey(string))
+ {
+ Object str = getHeaders().getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getBoolean can't use " + string + " item.");
+ }
+ else
+ {
+ return Boolean.valueOf((String) str);
+ }
+ }
+ else
+ {
+ b = Boolean.valueOf(null);
+ }
+ }
+
+ return b;
+ }
+
+ public char getCharacter(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Character c = getHeaders().getCharacter(string);
+
+ if (c == null)
+ {
+ if (getHeaders().isNullStringValue(string))
+ {
+ throw new NullPointerException("Cannot convert null char");
+ }
+ else
+ {
+ throw new MessageFormatException("getChar can't use " + string + " item.");
+ }
+ }
+ else
+ {
+ return (char) c;
+ }
+ }
+
+ public byte[] getBytes(String string) throws JMSException
+ {
+ return getBytes(new AMQShortString(string));
+ }
+
+ public byte[] getBytes(AMQShortString string) throws JMSException
+ {
+ checkPropertyName(string);
+
+ byte[] bs = getHeaders().getBytes(string);
+
+ if (bs == null)
+ {
+ throw new MessageFormatException("getBytes can't use " + string + " item.");
+ }
+ else
+ {
+ return bs;
+ }
+ }
+
+ public byte getByte(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Byte b = getHeaders().getByte(string);
+ if (b == null)
+ {
+ if (getHeaders().containsKey(string))
+ {
+ Object str = getHeaders().getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getByte can't use " + string + " item.");
+ }
+ else
+ {
+ return Byte.valueOf((String) str);
+ }
+ }
+ else
+ {
+ b = Byte.valueOf(null);
+ }
+ }
+
+ return b;
+ }
+
+ public short getShort(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Short s = getHeaders().getShort(string);
+
+ if (s == null)
+ {
+ s = Short.valueOf(getByte(string));
+ }
+
+ return s;
+ }
+
+ public int getInteger(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Integer i = getHeaders().getInteger(string);
+
+ if (i == null)
+ {
+ i = Integer.valueOf(getShort(string));
+ }
+
+ return i;
+ }
+
+ public long getLong(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Long l = getHeaders().getLong(string);
+
+ if (l == null)
+ {
+ l = Long.valueOf(getInteger(string));
+ }
+
+ return l;
+ }
+
+ public float getFloat(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Float f = getHeaders().getFloat(string);
+
+ if (f == null)
+ {
+ if (getHeaders().containsKey(string))
+ {
+ Object str = getHeaders().getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getFloat can't use " + string + " item.");
+ }
+ else
+ {
+ return Float.valueOf((String) str);
+ }
+ }
+ else
+ {
+ f = Float.valueOf(null);
+ }
+
+ }
+
+ return f;
+ }
+
+ public double getDouble(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ Double d = getHeaders().getDouble(string);
+
+ if (d == null)
+ {
+ d = Double.valueOf(getFloat(string));
+ }
+
+ return d;
+ }
+
+ public String getString(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ String s = getHeaders().getString(string);
+
+ if (s == null)
+ {
+ if (getHeaders().containsKey(string))
+ {
+ Object o = getHeaders().getObject(string);
+ if (o instanceof byte[])
+ {
+ throw new MessageFormatException("getObject couldn't find " + string + " item.");
+ }
+ else
+ {
+ if (o == null)
+ {
+ return null;
+ }
+ else
+ {
+ s = String.valueOf(o);
+ }
+ }
+ }//else return s // null;
+ }
+
+ return s;
+ }
+
+ public Object getObject(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ return getHeaders().getObject(string);
+ }
+
+ public void setBoolean(AMQShortString string, boolean b) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setBoolean(string, b);
+ }
+
+ public void setBoolean(String string, boolean b) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setBoolean(string, b);
+ }
+
+ public void setChar(String string, char c) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setChar(string, c);
+ }
+
+ public Object setBytes(AMQShortString string, byte[] bytes)
+ {
+ checkPropertyName(string);
+ return getHeaders().setBytes(string, bytes);
+ }
+
+ public Object setBytes(String string, byte[] bytes)
+ {
+ checkPropertyName(string);
+ return getHeaders().setBytes(string, bytes);
+ }
+
+ public Object setBytes(String string, byte[] bytes, int start, int length)
+ {
+ checkPropertyName(string);
+ return getHeaders().setBytes(string, bytes, start, length);
+ }
+
+ public void setByte(String string, byte b) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setByte(string, b);
+ }
+
+ public void setByte(AMQShortString string, byte b) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setByte(string, b);
+ }
+
+
+ public void setShort(String string, short i) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setShort(string, i);
+ }
+
+ public void setInteger(String string, int i) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setInteger(string, i);
+ }
+
+ public void setInteger(AMQShortString string, int i) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setInteger(string, i);
+ }
+
+ public void setLong(String string, long l) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setLong(string, l);
+ }
+
+ public void setFloat(String string, float v) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setFloat(string, v);
+ }
+
+ public void setDouble(String string, double v) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setDouble(string, v);
+ }
+
+ public void setString(String string, String string1) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setString(string, string1);
+ }
+
+ public void setString(AMQShortString string, String string1) throws JMSException
+ {
+ checkPropertyName(string);
+ getHeaders().setString(string, string1);
+ }
+
+ public void setObject(String string, Object object) throws JMSException
+ {
+ checkPropertyName(string);
+ try
+ {
+ getHeaders().setObject(string, object);
+ }
+ catch (AMQPInvalidClassException aice)
+ {
+ MessageFormatException mfe = new MessageFormatException("Only primatives are allowed object is:" + object.getClass());
+ mfe.setLinkedException(aice);
+ throw mfe;
+ }
+ }
+
+ public boolean itemExists(String string) throws JMSException
+ {
+ checkPropertyName(string);
+ return getHeaders().containsKey(string);
+ }
+
+ public Enumeration getPropertyNames()
+ {
+ return getHeaders().getPropertyNames();
+ }
+
+ public void clear()
+ {
+ getHeaders().clear();
+ }
+
+ public boolean propertyExists(AMQShortString propertyName)
+ {
+ checkPropertyName(propertyName);
+ return getHeaders().propertyExists(propertyName);
+ }
+
+ public boolean propertyExists(String propertyName)
+ {
+ checkPropertyName(propertyName);
+ return getHeaders().propertyExists(propertyName);
+ }
+
+ public Object put(Object key, Object value)
+ {
+ checkPropertyName(key.toString());
+ return getHeaders().setObject(key.toString(), value);
+ }
+
+ public Object remove(AMQShortString propertyName)
+ {
+ checkPropertyName(propertyName);
+ return getHeaders().remove(propertyName);
+ }
+
+ public Object remove(String propertyName)
+ {
+ checkPropertyName(propertyName);
+ return getHeaders().remove(propertyName);
+ }
+
+ public boolean isEmpty()
+ {
+ return getHeaders().isEmpty();
+ }
+
+ public void writeToBuffer(ByteBuffer data)
+ {
+ getHeaders().writeToBuffer(data);
+ }
+
+ public Enumeration getMapNames()
+ {
+ return getPropertyNames();
+ }
+
+ protected static void checkPropertyName(CharSequence propertyName)
+ {
+ if (propertyName == null)
+ {
+ throw new IllegalArgumentException("Property name must not be null");
+ }
+ else if (propertyName.length() == 0)
+ {
+ throw new IllegalArgumentException("Property name must not be the empty string");
+ }
+
+ checkIdentiferFormat(propertyName);
+ }
+
+ protected static void checkIdentiferFormat(CharSequence propertyName)
+ {
+// JMS requirements 3.5.1 Property Names
+// Identifiers:
+// - An identifier is an unlimited-length character sequence that must begin
+// with a Java identifier start character; all following characters must be Java
+// identifier part characters. An identifier start character is any character for
+// which the method Character.isJavaIdentifierStart returns true. This includes
+// '_' and '$'. An identifier part character is any character for which the
+// method Character.isJavaIdentifierPart returns true.
+// - Identifiers cannot be the names NULL, TRUE, or FALSE.
+// � Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
+// ESCAPE.
+// � Identifiers are either header field references or property references. The
+// type of a property value in a message selector corresponds to the type
+// used to set the property. If a property that does not exist in a message is
+// referenced, its value is NULL. The semantics of evaluating NULL values
+// in a selector are described in Section 3.8.1.2, �Null Values.�
+// � The conversions that apply to the get methods for properties do not
+// apply when a property is used in a message selector expression. For
+// example, suppose you set a property as a string value, as in the
+// following:
+// myMessage.setStringProperty("NumberOfOrders", "2");
+// The following expression in a message selector would evaluate to false,
+// because a string cannot be used in an arithmetic expression:
+// "NumberOfOrders > 1"
+// � Identifiers are case sensitive.
+// � Message header field references are restricted to JMSDeliveryMode,
+// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
+// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
+// null and if so are treated as a NULL value.
+
+ if (Boolean.getBoolean("strict-jms"))
+ {
+ // JMS start character
+ if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
+ }
+
+ // JMS part character
+ int length = propertyName.length();
+ for (int c = 1; c < length; c++)
+ {
+ if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
+ }
+ }
+
+ // JMS invalid names
+ if ((propertyName.equals("NULL")
+ || propertyName.equals("TRUE")
+ || propertyName.equals("FALSE")
+ || propertyName.equals("NOT")
+ || propertyName.equals("AND")
+ || propertyName.equals("OR")
+ || propertyName.equals("BETWEEN")
+ || propertyName.equals("LIKE")
+ || propertyName.equals("IN")
+ || propertyName.equals("IS")
+ || propertyName.equals("ESCAPE")))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
+ }
+ }
+
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQMethodNotImplementedException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQMethodNotImplementedException.java
index 5185278eef..2c99b9a97b 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQMethodNotImplementedException.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/state/AMQMethodNotImplementedException.java
@@ -1,32 +1,32 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.client.state;
-
-import org.apache.qpid.framing.AMQMethodBody;
-import org.apache.qpid.AMQException;
-
-public class AMQMethodNotImplementedException extends AMQException
-{
- public AMQMethodNotImplementedException(AMQMethodBody body)
- {
- super(null, "Unexpected Method Received: " + body.getClass().getName(), null);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.state;
+
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.AMQException;
+
+public class AMQMethodNotImplementedException extends AMQException
+{
+ public AMQMethodNotImplementedException(AMQMethodBody body)
+ {
+ super(null, "Unexpected Method Received: " + body.getClass().getName(), null);
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/jms/Message.java b/qpid/java/client/src/main/java/org/apache/qpid/jms/Message.java
index 6752ee616f..e65f9ad2f4 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/jms/Message.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/jms/Message.java
@@ -1,28 +1,28 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.jms;
-
-import javax.jms.JMSException;
-
-public interface Message extends javax.jms.Message
-{
- public void acknowledgeThis() throws JMSException;
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.jms;
+
+import javax.jms.JMSException;
+
+public interface Message extends javax.jms.Message
+{
+ public void acknowledgeThis() throws JMSException;
+}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
index a5279a195b..1738db7239 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
@@ -1,104 +1,104 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.test.unit.basic;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.testutil.QpidTestCase;
-
-import javax.jms.Session;
-import javax.jms.QueueSession;
-import javax.jms.Queue;
-import javax.jms.QueueSender;
-import javax.jms.TextMessage;
-import javax.jms.InvalidDestinationException;
-
-public class InvalidDestinationTest extends QpidTestCase
-{
- private AMQConnection _connection;
-
- protected void setUp() throws Exception
- {
- super.setUp();
- _connection = (AMQConnection) getConnection("guest", "guest");
- }
-
- protected void tearDown() throws Exception
- {
- _connection.close();
- super.tearDown();
- }
-
-
-
- public void testInvalidDestination() throws Exception
- {
- Queue invalidDestination = new AMQQueue("amq.direct","unknownQ");
- AMQQueue validDestination = new AMQQueue("amq.direct","knownQ");
- QueueSession queueSession = _connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // This is the only easy way to create and bind a queue from the API :-(
- queueSession.createConsumer(validDestination);
-
- QueueSender sender = queueSession.createSender(invalidDestination);
- TextMessage msg = queueSession.createTextMessage("Hello");
- try
- {
- sender.send(msg);
- fail("Expected InvalidDestinationException");
- }
- catch (InvalidDestinationException ex)
- {
- // pass
- }
- sender.close();
-
- sender = queueSession.createSender(null);
- invalidDestination = new AMQQueue("amq.direct","unknownQ");
-
- try
- {
- sender.send(invalidDestination,msg);
- fail("Expected InvalidDestinationException");
- }
- catch (InvalidDestinationException ex)
- {
- // pass
- }
- sender.send(validDestination,msg);
- sender.close();
- validDestination = new AMQQueue("amq.direct","knownQ");
- sender = queueSession.createSender(validDestination);
- sender.send(msg);
-
-
-
-
- }
-
-
- public static junit.framework.Test suite()
- {
-
- return new junit.framework.TestSuite(InvalidDestinationTest.class);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.test.unit.basic;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.testutil.QpidTestCase;
+
+import javax.jms.Session;
+import javax.jms.QueueSession;
+import javax.jms.Queue;
+import javax.jms.QueueSender;
+import javax.jms.TextMessage;
+import javax.jms.InvalidDestinationException;
+
+public class InvalidDestinationTest extends QpidTestCase
+{
+ private AMQConnection _connection;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ _connection = (AMQConnection) getConnection("guest", "guest");
+ }
+
+ protected void tearDown() throws Exception
+ {
+ _connection.close();
+ super.tearDown();
+ }
+
+
+
+ public void testInvalidDestination() throws Exception
+ {
+ Queue invalidDestination = new AMQQueue("amq.direct","unknownQ");
+ AMQQueue validDestination = new AMQQueue("amq.direct","knownQ");
+ QueueSession queueSession = _connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // This is the only easy way to create and bind a queue from the API :-(
+ queueSession.createConsumer(validDestination);
+
+ QueueSender sender = queueSession.createSender(invalidDestination);
+ TextMessage msg = queueSession.createTextMessage("Hello");
+ try
+ {
+ sender.send(msg);
+ fail("Expected InvalidDestinationException");
+ }
+ catch (InvalidDestinationException ex)
+ {
+ // pass
+ }
+ sender.close();
+
+ sender = queueSession.createSender(null);
+ invalidDestination = new AMQQueue("amq.direct","unknownQ");
+
+ try
+ {
+ sender.send(invalidDestination,msg);
+ fail("Expected InvalidDestinationException");
+ }
+ catch (InvalidDestinationException ex)
+ {
+ // pass
+ }
+ sender.send(validDestination,msg);
+ sender.close();
+ validDestination = new AMQQueue("amq.direct","knownQ");
+ sender = queueSession.createSender(validDestination);
+ sender.send(msg);
+
+
+
+
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+
+ return new junit.framework.TestSuite(InvalidDestinationTest.class);
+ }
+}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
index 34197f2608..46b99fac8d 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
@@ -1,221 +1,221 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.test.unit.client.temporaryqueue;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TemporaryQueue;
-import javax.jms.TextMessage;
-import junit.framework.Assert;
-
-import org.apache.qpid.testutil.QpidTestCase;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.transport.TransportConnection;
-
-import java.util.List;
-import java.util.LinkedList;
-
-public class TemporaryQueueTest extends QpidTestCase
-{
- protected void setUp() throws Exception
- {
- super.setUp();
- }
-
- protected void tearDown() throws Exception
- {
- super.tearDown();
- }
-
- protected Connection createConnection() throws Exception
- {
- return getConnection("guest", "guest");
- }
-
- public void testTempoaryQueue() throws Exception
- {
- Connection conn = createConnection();
- Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
- TemporaryQueue queue = session.createTemporaryQueue();
- assertNotNull(queue);
- MessageProducer producer = session.createProducer(queue);
- MessageConsumer consumer = session.createConsumer(queue);
- conn.start();
- producer.send(session.createTextMessage("hello"));
- TextMessage tm = (TextMessage) consumer.receive(2000);
- assertNotNull(tm);
- assertEquals("hello", tm.getText());
-
- try
- {
- queue.delete();
- fail("Expected JMSException : should not be able to delete while there are active consumers");
- }
- catch (JMSException je)
- {
- ; //pass
- }
-
- consumer.close();
-
- try
- {
- queue.delete();
- }
- catch (JMSException je)
- {
- fail("Unexpected Exception: " + je.getMessage());
- }
-
- conn.close();
- }
-
- public void tUniqueness() throws Exception
- {
- int numProcs = Runtime.getRuntime().availableProcessors();
- final int threadsProc = 5;
-
- runUniqueness(1, 10);
- runUniqueness(numProcs * threadsProc, 10);
- runUniqueness(numProcs * threadsProc, 100);
- runUniqueness(numProcs * threadsProc, 500);
- }
-
- void runUniqueness(int makers, int queues) throws Exception
- {
- Connection connection = createConnection();
-
- Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- List<TempQueueMaker> tqList = new LinkedList<TempQueueMaker>();
-
- //Create Makers
- for (int m = 0; m < makers; m++)
- {
- tqList.add(new TempQueueMaker(session, queues));
- }
-
-
- List<Thread> threadList = new LinkedList<Thread>();
-
- //Create Makers
- for (TempQueueMaker maker : tqList)
- {
- threadList.add(new Thread(maker));
- }
-
- //Start threads
- for (Thread thread : threadList)
- {
- thread.start();
- }
-
- // Join Threads
- for (Thread thread : threadList)
- {
- try
- {
- thread.join();
- }
- catch (InterruptedException e)
- {
- fail("Couldn't correctly join threads");
- }
- }
-
-
- List<AMQQueue> list = new LinkedList<AMQQueue>();
-
- // Test values
- for (TempQueueMaker maker : tqList)
- {
- check(maker, list);
- }
-
- Assert.assertEquals("Not enough queues made.", makers * queues, list.size());
-
- connection.close();
- }
-
- private void check(TempQueueMaker tq, List<AMQQueue> list)
- {
- for (AMQQueue q : tq.getList())
- {
- if (list.contains(q))
- {
- fail(q + " already exists.");
- }
- else
- {
- list.add(q);
- }
- }
- }
-
-
- class TempQueueMaker implements Runnable
- {
- List<AMQQueue> _queues;
- Session _session;
- private int _count;
-
-
- TempQueueMaker(Session session, int queues) throws JMSException
- {
- _queues = new LinkedList<AMQQueue>();
-
- _count = queues;
-
- _session = session;
- }
-
- public void run()
- {
- int i = 0;
- try
- {
- for (; i < _count; i++)
- {
- _queues.add((AMQQueue) _session.createTemporaryQueue());
- }
- }
- catch (JMSException jmse)
- {
- //stop
- }
- }
-
- List<AMQQueue> getList()
- {
- return _queues;
- }
- }
-
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(TemporaryQueueTest.class);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.test.unit.client.temporaryqueue;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TemporaryQueue;
+import javax.jms.TextMessage;
+import junit.framework.Assert;
+
+import org.apache.qpid.testutil.QpidTestCase;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.transport.TransportConnection;
+
+import java.util.List;
+import java.util.LinkedList;
+
+public class TemporaryQueueTest extends QpidTestCase
+{
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ protected Connection createConnection() throws Exception
+ {
+ return getConnection("guest", "guest");
+ }
+
+ public void testTempoaryQueue() throws Exception
+ {
+ Connection conn = createConnection();
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryQueue queue = session.createTemporaryQueue();
+ assertNotNull(queue);
+ MessageProducer producer = session.createProducer(queue);
+ MessageConsumer consumer = session.createConsumer(queue);
+ conn.start();
+ producer.send(session.createTextMessage("hello"));
+ TextMessage tm = (TextMessage) consumer.receive(2000);
+ assertNotNull(tm);
+ assertEquals("hello", tm.getText());
+
+ try
+ {
+ queue.delete();
+ fail("Expected JMSException : should not be able to delete while there are active consumers");
+ }
+ catch (JMSException je)
+ {
+ ; //pass
+ }
+
+ consumer.close();
+
+ try
+ {
+ queue.delete();
+ }
+ catch (JMSException je)
+ {
+ fail("Unexpected Exception: " + je.getMessage());
+ }
+
+ conn.close();
+ }
+
+ public void tUniqueness() throws Exception
+ {
+ int numProcs = Runtime.getRuntime().availableProcessors();
+ final int threadsProc = 5;
+
+ runUniqueness(1, 10);
+ runUniqueness(numProcs * threadsProc, 10);
+ runUniqueness(numProcs * threadsProc, 100);
+ runUniqueness(numProcs * threadsProc, 500);
+ }
+
+ void runUniqueness(int makers, int queues) throws Exception
+ {
+ Connection connection = createConnection();
+
+ Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ List<TempQueueMaker> tqList = new LinkedList<TempQueueMaker>();
+
+ //Create Makers
+ for (int m = 0; m < makers; m++)
+ {
+ tqList.add(new TempQueueMaker(session, queues));
+ }
+
+
+ List<Thread> threadList = new LinkedList<Thread>();
+
+ //Create Makers
+ for (TempQueueMaker maker : tqList)
+ {
+ threadList.add(new Thread(maker));
+ }
+
+ //Start threads
+ for (Thread thread : threadList)
+ {
+ thread.start();
+ }
+
+ // Join Threads
+ for (Thread thread : threadList)
+ {
+ try
+ {
+ thread.join();
+ }
+ catch (InterruptedException e)
+ {
+ fail("Couldn't correctly join threads");
+ }
+ }
+
+
+ List<AMQQueue> list = new LinkedList<AMQQueue>();
+
+ // Test values
+ for (TempQueueMaker maker : tqList)
+ {
+ check(maker, list);
+ }
+
+ Assert.assertEquals("Not enough queues made.", makers * queues, list.size());
+
+ connection.close();
+ }
+
+ private void check(TempQueueMaker tq, List<AMQQueue> list)
+ {
+ for (AMQQueue q : tq.getList())
+ {
+ if (list.contains(q))
+ {
+ fail(q + " already exists.");
+ }
+ else
+ {
+ list.add(q);
+ }
+ }
+ }
+
+
+ class TempQueueMaker implements Runnable
+ {
+ List<AMQQueue> _queues;
+ Session _session;
+ private int _count;
+
+
+ TempQueueMaker(Session session, int queues) throws JMSException
+ {
+ _queues = new LinkedList<AMQQueue>();
+
+ _count = queues;
+
+ _session = session;
+ }
+
+ public void run()
+ {
+ int i = 0;
+ try
+ {
+ for (; i < _count; i++)
+ {
+ _queues.add((AMQQueue) _session.createTemporaryQueue());
+ }
+ }
+ catch (JMSException jmse)
+ {
+ //stop
+ }
+ }
+
+ List<AMQQueue> getList()
+ {
+ return _queues;
+ }
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(TemporaryQueueTest.class);
+ }
+}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
index d25986d991..54b2ee95f4 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java
@@ -1,144 +1,144 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.unit.close;
-
-import junit.framework.Assert;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.QpidTestCase;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.junit.concurrency.TestRunnable;
-import org.apache.qpid.junit.concurrency.ThreadTestCoordinator;
-
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-
-/**
- * This test forces the situation where a session is closed whilst a message consumer is still in its onMessage method.
- * Running in AUTO_ACK mode, the close call ought to wait until the onMessage method completes, and the ack is sent
- * before closing the connection.
- *
- * <p><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Check that
- * closing a connection whilst handling a message, blocks till completion of the handler. </table>
- */
-public class CloseBeforeAckTest extends QpidTestCase
-{
- private static final Logger log = LoggerFactory.getLogger(CloseBeforeAckTest.class);
-
- Connection connection;
- Session session;
- public static final String TEST_QUEUE_NAME = "TestQueue";
- private int TEST_COUNT = 25;
-
- class TestThread1 extends TestRunnable implements MessageListener
- {
- public void runWithExceptions() throws Exception
- {
- // Set this up to listen for message on the test session.
- session.createConsumer(session.createQueue(TEST_QUEUE_NAME)).setMessageListener(this);
- }
-
- public void onMessage(Message message)
- {
- // Give thread 2 permission to close the session.
- allow(new int[] { 1 });
-
- // Wait until thread 2 has closed the connection, or is blocked waiting for this to complete.
- waitFor(new int[] { 1 }, true);
- }
- }
-
- TestThread1 testThread1 = new TestThread1();
-
- TestRunnable testThread2 =
- new TestRunnable()
- {
- public void runWithExceptions() throws Exception
- {
- // Send a message to be picked up by thread 1.
- session.createProducer(null).send(session.createQueue(TEST_QUEUE_NAME),
- session.createTextMessage("Hi there thread 1!"));
-
- // Wait for thread 1 to pick up the message and give permission to continue.
- waitFor(new int[] { 0 }, false);
-
- // Close the connection.
- session.close();
-
- // Allow thread 1 to continue to completion, if it is erronously still waiting.
- allow(new int[] { 1 });
- }
- };
-
- public void testCloseBeforeAutoAck_QPID_397() throws Exception
- {
- // Create a session in auto acknowledge mode. This problem shows up in auto acknowledge if the client acks
- // message at the end of the onMessage method, after a close has been sent.
- session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- ThreadTestCoordinator tt = new ThreadTestCoordinator(2);
-
- tt.addTestThread(testThread1, 0);
- tt.addTestThread(testThread2, 1);
- tt.setDeadlockTimeout(500);
- tt.run();
-
- String errorMessage = tt.joinAndRetrieveMessages();
-
- // Print any error messages or exceptions.
- log.debug(errorMessage);
-
- if (!tt.getExceptions().isEmpty())
- {
- for (Exception e : tt.getExceptions())
- {
- log.debug("Exception thrown during test thread: ", e);
- }
- }
-
- Assert.assertTrue(errorMessage, "".equals(errorMessage));
- }
-
- public void closeBeforeAutoAckManyTimes() throws Exception
- {
- for (int i = 0; i < TEST_COUNT; i++)
- {
- testCloseBeforeAutoAck_QPID_397();
- }
- }
-
- protected void setUp() throws Exception
- {
- super.setUp();
- connection = getConnection("guest", "guest");
- }
-
- protected void tearDown() throws Exception
- {
- super.tearDown();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.unit.close;
+
+import junit.framework.Assert;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.testutil.QpidTestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.junit.concurrency.TestRunnable;
+import org.apache.qpid.junit.concurrency.ThreadTestCoordinator;
+
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Session;
+
+/**
+ * This test forces the situation where a session is closed whilst a message consumer is still in its onMessage method.
+ * Running in AUTO_ACK mode, the close call ought to wait until the onMessage method completes, and the ack is sent
+ * before closing the connection.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Check that
+ * closing a connection whilst handling a message, blocks till completion of the handler. </table>
+ */
+public class CloseBeforeAckTest extends QpidTestCase
+{
+ private static final Logger log = LoggerFactory.getLogger(CloseBeforeAckTest.class);
+
+ Connection connection;
+ Session session;
+ public static final String TEST_QUEUE_NAME = "TestQueue";
+ private int TEST_COUNT = 25;
+
+ class TestThread1 extends TestRunnable implements MessageListener
+ {
+ public void runWithExceptions() throws Exception
+ {
+ // Set this up to listen for message on the test session.
+ session.createConsumer(session.createQueue(TEST_QUEUE_NAME)).setMessageListener(this);
+ }
+
+ public void onMessage(Message message)
+ {
+ // Give thread 2 permission to close the session.
+ allow(new int[] { 1 });
+
+ // Wait until thread 2 has closed the connection, or is blocked waiting for this to complete.
+ waitFor(new int[] { 1 }, true);
+ }
+ }
+
+ TestThread1 testThread1 = new TestThread1();
+
+ TestRunnable testThread2 =
+ new TestRunnable()
+ {
+ public void runWithExceptions() throws Exception
+ {
+ // Send a message to be picked up by thread 1.
+ session.createProducer(null).send(session.createQueue(TEST_QUEUE_NAME),
+ session.createTextMessage("Hi there thread 1!"));
+
+ // Wait for thread 1 to pick up the message and give permission to continue.
+ waitFor(new int[] { 0 }, false);
+
+ // Close the connection.
+ session.close();
+
+ // Allow thread 1 to continue to completion, if it is erronously still waiting.
+ allow(new int[] { 1 });
+ }
+ };
+
+ public void testCloseBeforeAutoAck_QPID_397() throws Exception
+ {
+ // Create a session in auto acknowledge mode. This problem shows up in auto acknowledge if the client acks
+ // message at the end of the onMessage method, after a close has been sent.
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ ThreadTestCoordinator tt = new ThreadTestCoordinator(2);
+
+ tt.addTestThread(testThread1, 0);
+ tt.addTestThread(testThread2, 1);
+ tt.setDeadlockTimeout(500);
+ tt.run();
+
+ String errorMessage = tt.joinAndRetrieveMessages();
+
+ // Print any error messages or exceptions.
+ log.debug(errorMessage);
+
+ if (!tt.getExceptions().isEmpty())
+ {
+ for (Exception e : tt.getExceptions())
+ {
+ log.debug("Exception thrown during test thread: ", e);
+ }
+ }
+
+ Assert.assertTrue(errorMessage, "".equals(errorMessage));
+ }
+
+ public void closeBeforeAutoAckManyTimes() throws Exception
+ {
+ for (int i = 0; i < TEST_COUNT; i++)
+ {
+ testCloseBeforeAutoAck_QPID_397();
+ }
+ }
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ connection = getConnection("guest", "guest");
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
index 0b9d0bdc2d..131cbd5f68 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java
@@ -1,89 +1,89 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.test.unit.message;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.testutil.QpidTestCase;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.jms.Connection;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-/**
- * @author Apache Software Foundation
- */
-public class JMSDestinationTest extends QpidTestCase
-{
- private static final Logger _logger = LoggerFactory.getLogger(JMSDestinationTest.class);
-
-
- protected void setUp() throws Exception
- {
- super.setUp();
- }
-
- protected void tearDown() throws Exception
- {
- super.tearDown();
- }
-
- public void testJMSDestination() throws Exception
- {
- AMQConnection con = (AMQConnection) getConnection("guest", "guest");
- AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- Queue queue =
- new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false,
- true);
- MessageConsumer consumer = consumerSession.createConsumer(queue);
-
- Connection con2 = (AMQConnection) getConnection("guest", "guest");
- Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- MessageProducer producer = producerSession.createProducer(queue);
-
- TextMessage sentMsg = producerSession.createTextMessage("hello");
- assertNull(sentMsg.getJMSDestination());
-
- producer.send(sentMsg);
-
- assertEquals(sentMsg.getJMSDestination(), queue);
-
- con2.close();
-
- con.start();
-
- TextMessage rm = (TextMessage) consumer.receive();
- assertNotNull(rm);
-
- assertEquals(rm.getJMSDestination(), queue);
- con.close();
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.test.unit.message;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.testutil.QpidTestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jms.Connection;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class JMSDestinationTest extends QpidTestCase
+{
+ private static final Logger _logger = LoggerFactory.getLogger(JMSDestinationTest.class);
+
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ public void testJMSDestination() throws Exception
+ {
+ AMQConnection con = (AMQConnection) getConnection("guest", "guest");
+ AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ Queue queue =
+ new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false,
+ true);
+ MessageConsumer consumer = consumerSession.createConsumer(queue);
+
+ Connection con2 = (AMQConnection) getConnection("guest", "guest");
+ Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(queue);
+
+ TextMessage sentMsg = producerSession.createTextMessage("hello");
+ assertNull(sentMsg.getJMSDestination());
+
+ producer.send(sentMsg);
+
+ assertEquals(sentMsg.getJMSDestination(), queue);
+
+ con2.close();
+
+ con.start();
+
+ TextMessage rm = (TextMessage) consumer.receive();
+ assertNotNull(rm);
+
+ assertEquals(rm.getJMSDestination(), queue);
+ con.close();
+ }
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/AMQUnknownExchangeType.java b/qpid/java/common/src/main/java/org/apache/qpid/AMQUnknownExchangeType.java
index b31765ce66..0eefc03016 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/AMQUnknownExchangeType.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/AMQUnknownExchangeType.java
@@ -1,43 +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;
-
-/**
- * AMQUnknownExchangeType represents coding error where unknown exchange type requested from exchange factory.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Represents unknown exchange type request.
- * <tr><td>
- *
- * @todo Not an AMQP exception as no status code.
- *
- * @todo Represent coding error, where unknown exchange type is requested by passing a string parameter. Use a type safe
- * enum for the exchange type, or replace with IllegalArgumentException. Should be runtime.
- */
-public class AMQUnknownExchangeType extends AMQException
-{
- public AMQUnknownExchangeType(String message, Throwable cause)
- {
- super(null, message, cause);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid;
+
+/**
+ * AMQUnknownExchangeType represents coding error where unknown exchange type requested from exchange factory.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents unknown exchange type request.
+ * <tr><td>
+ *
+ * @todo Not an AMQP exception as no status code.
+ *
+ * @todo Represent coding error, where unknown exchange type is requested by passing a string parameter. Use a type safe
+ * enum for the exchange type, or replace with IllegalArgumentException. Should be runtime.
+ */
+public class AMQUnknownExchangeType extends AMQException
+{
+ public AMQUnknownExchangeType(String message, Throwable cause)
+ {
+ super(null, message, cause);
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
index 64af717342..ad7f36f790 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
@@ -1,96 +1,96 @@
-package org.apache.qpid.framing;
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.AMQChannelException;
-import org.apache.qpid.AMQConnectionException;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-
-public abstract class AMQMethodBodyImpl implements AMQMethodBody
-{
- public static final byte TYPE = 1;
-
- public AMQMethodBodyImpl()
- {
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
-
- /** unsigned short */
- abstract protected int getBodySize();
-
-
- public AMQFrame generateFrame(int channelId)
- {
- return new AMQFrame(channelId, this);
- }
-
- /**
- * Creates an AMQChannelException for the corresponding body type (a channel exception should include the class and
- * method ids of the body it resulted from).
- */
-
- /**
- * Convenience Method to create a channel not found exception
- *
- * @param channelId The channel id that is not found
- *
- * @return new AMQChannelException
- */
- public AMQChannelException getChannelNotFoundException(int channelId)
- {
- return getChannelException(AMQConstant.NOT_FOUND, "Channel not found for id:" + channelId);
- }
-
- public AMQChannelException getChannelException(AMQConstant code, String message)
- {
- return new AMQChannelException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), null);
- }
-
- public AMQChannelException getChannelException(AMQConstant code, String message, Throwable cause)
- {
- return new AMQChannelException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), cause);
- }
-
- public AMQConnectionException getConnectionException(AMQConstant code, String message)
- {
- return new AMQConnectionException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), null);
- }
-
- public AMQConnectionException getConnectionException(AMQConstant code, String message, Throwable cause)
- {
- return new AMQConnectionException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), cause);
- }
-
- public void handle(final int channelId, final AMQVersionAwareProtocolSession session) throws AMQException
- {
- session.methodFrameReceived(channelId, this);
- }
-
-}
+package org.apache.qpid.framing;
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQChannelException;
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+
+public abstract class AMQMethodBodyImpl implements AMQMethodBody
+{
+ public static final byte TYPE = 1;
+
+ public AMQMethodBodyImpl()
+ {
+ }
+
+ public byte getFrameType()
+ {
+ return TYPE;
+ }
+
+
+ /** unsigned short */
+ abstract protected int getBodySize();
+
+
+ public AMQFrame generateFrame(int channelId)
+ {
+ return new AMQFrame(channelId, this);
+ }
+
+ /**
+ * Creates an AMQChannelException for the corresponding body type (a channel exception should include the class and
+ * method ids of the body it resulted from).
+ */
+
+ /**
+ * Convenience Method to create a channel not found exception
+ *
+ * @param channelId The channel id that is not found
+ *
+ * @return new AMQChannelException
+ */
+ public AMQChannelException getChannelNotFoundException(int channelId)
+ {
+ return getChannelException(AMQConstant.NOT_FOUND, "Channel not found for id:" + channelId);
+ }
+
+ public AMQChannelException getChannelException(AMQConstant code, String message)
+ {
+ return new AMQChannelException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), null);
+ }
+
+ public AMQChannelException getChannelException(AMQConstant code, String message, Throwable cause)
+ {
+ return new AMQChannelException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), cause);
+ }
+
+ public AMQConnectionException getConnectionException(AMQConstant code, String message)
+ {
+ return new AMQConnectionException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), null);
+ }
+
+ public AMQConnectionException getConnectionException(AMQConstant code, String message, Throwable cause)
+ {
+ return new AMQConnectionException(code, message, getClazz(), getMethod(), getMajor(), getMinor(), cause);
+ }
+
+ public void handle(final int channelId, final AMQVersionAwareProtocolSession session) throws AMQException
+ {
+ session.methodFrameReceived(channelId, this);
+ }
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
index 0030742e94..0c61d9db3c 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyInstanceFactory.java
@@ -1,30 +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.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-
-public abstract interface AMQMethodBodyInstanceFactory
-{
- public AMQMethodBody newInstance(ByteBuffer buffer, long size) throws AMQFrameDecodingException;
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+
+public abstract interface AMQMethodBodyInstanceFactory
+{
+ public AMQMethodBody newInstance(ByteBuffer buffer, long size) throws AMQFrameDecodingException;
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java
index 4ffc9e0066..bfcc38ad60 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodFactory.java
@@ -1,90 +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.
- *
- */
-package org.apache.qpid.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-
-public interface AMQMethodFactory
-{
-
- // Connection Methods
-
- ConnectionCloseBody createConnectionClose();
-
- // Access Methods
-
- AccessRequestBody createAccessRequest(boolean active, boolean exclusive, boolean passive, boolean read, AMQShortString realm, boolean write);
-
-
- // Tx Methods
-
- TxSelectBody createTxSelect();
-
- TxCommitBody createTxCommit();
-
- TxRollbackBody createTxRollback();
-
- // Channel Methods
-
- ChannelOpenBody createChannelOpen();
-
- ChannelCloseBody createChannelClose(int replyCode, AMQShortString replyText);
-
- ChannelFlowBody createChannelFlow(boolean active);
-
-
- // Exchange Methods
-
-
- ExchangeBoundBody createExchangeBound(AMQShortString exchangeName,
- AMQShortString queueName,
- AMQShortString routingKey);
-
- ExchangeDeclareBody createExchangeDeclare(AMQShortString name, AMQShortString type, int ticket);
-
-
- // Queue Methods
-
- QueueDeclareBody createQueueDeclare(AMQShortString name, FieldTable arguments, boolean autoDelete, boolean durable, boolean exclusive, boolean passive, int ticket);
-
- QueueBindBody createQueueBind(AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey, FieldTable arguments, int ticket);
-
- QueueDeleteBody createQueueDelete(AMQShortString queueName, boolean ifEmpty, boolean ifUnused, int ticket);
-
-
- // Message Methods
-
- // In different versions of the protocol we change the class used for message transfer
- // abstract this out so the appropriate methods are created
- AMQMethodBody createRecover(boolean requeue);
-
- AMQMethodBody createConsumer(AMQShortString tag, AMQShortString queueName, FieldTable arguments, boolean noAck, boolean exclusive, boolean noLocal, int ticket);
-
- AMQMethodBody createConsumerCancel(AMQShortString consumerTag);
-
- AMQMethodBody createAcknowledge(long deliveryTag, boolean multiple);
-
- AMQMethodBody createRejectBody(long deliveryTag, boolean requeue);
-
- AMQMethodBody createMessageQos(int prefetchCount, int prefetchSize);
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+
+public interface AMQMethodFactory
+{
+
+ // Connection Methods
+
+ ConnectionCloseBody createConnectionClose();
+
+ // Access Methods
+
+ AccessRequestBody createAccessRequest(boolean active, boolean exclusive, boolean passive, boolean read, AMQShortString realm, boolean write);
+
+
+ // Tx Methods
+
+ TxSelectBody createTxSelect();
+
+ TxCommitBody createTxCommit();
+
+ TxRollbackBody createTxRollback();
+
+ // Channel Methods
+
+ ChannelOpenBody createChannelOpen();
+
+ ChannelCloseBody createChannelClose(int replyCode, AMQShortString replyText);
+
+ ChannelFlowBody createChannelFlow(boolean active);
+
+
+ // Exchange Methods
+
+
+ ExchangeBoundBody createExchangeBound(AMQShortString exchangeName,
+ AMQShortString queueName,
+ AMQShortString routingKey);
+
+ ExchangeDeclareBody createExchangeDeclare(AMQShortString name, AMQShortString type, int ticket);
+
+
+ // Queue Methods
+
+ QueueDeclareBody createQueueDeclare(AMQShortString name, FieldTable arguments, boolean autoDelete, boolean durable, boolean exclusive, boolean passive, int ticket);
+
+ QueueBindBody createQueueBind(AMQShortString queueName, AMQShortString exchangeName, AMQShortString routingKey, FieldTable arguments, int ticket);
+
+ QueueDeleteBody createQueueDelete(AMQShortString queueName, boolean ifEmpty, boolean ifUnused, int ticket);
+
+
+ // Message Methods
+
+ // In different versions of the protocol we change the class used for message transfer
+ // abstract this out so the appropriate methods are created
+ AMQMethodBody createRecover(boolean requeue);
+
+ AMQMethodBody createConsumer(AMQShortString tag, AMQShortString queueName, FieldTable arguments, boolean noAck, boolean exclusive, boolean noLocal, int ticket);
+
+ AMQMethodBody createConsumerCancel(AMQShortString consumerTag);
+
+ AMQMethodBody createAcknowledge(long deliveryTag, boolean multiple);
+
+ AMQMethodBody createRejectBody(long deliveryTag, boolean requeue);
+
+ AMQMethodBody createMessageQos(int prefetchCount, int prefetchSize);
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
index 2c356d072c..14fb63da03 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
@@ -1,795 +1,795 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-import java.math.BigDecimal;
-
-/**
- * AMQType is a type that represents the different possible AMQP field table types. It provides operations for each
- * of the types to perform tasks such as calculating the size of an instance of the type, converting types between AMQP
- * and Java native types, and reading and writing instances of AMQP types in binary formats to and from byte buffers.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Get the equivalent one byte identifier for a type.
- * <tr><td> Calculate the size of an instance of an AMQP parameter type. <td> {@link EncodingUtils}
- * <tr><td> Convert an instance of an AMQP parameter into a compatable Java object tagged with its AMQP type.
- * <td> {@link AMQTypedValue}
- * <tr><td> Write an instance of an AMQP parameter type to a byte buffer. <td> {@link EncodingUtils}
- * <tr><td> Read an instance of an AMQP parameter from a byte buffer. <td> {@link EncodingUtils}
- * </table>
- */
-public enum AMQType
-{
- LONG_STRING('S')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedLongStringLength((String) value);
- }
-
- public String toNativeValue(Object value)
- {
- if (value != null)
- {
- return value.toString();
- }
- else
- {
- throw new NullPointerException("Cannot convert: null to String.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLongString(buffer);
- }
- },
-
- INTEGER('i')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.unsignedIntegerLength();
- }
-
- public Long toNativeValue(Object value)
- {
- if (value instanceof Long)
- {
- return (Long) value;
- }
- else if (value instanceof Integer)
- {
- return ((Integer) value).longValue();
- }
- else if (value instanceof Short)
- {
- return ((Short) value).longValue();
- }
- else if (value instanceof Byte)
- {
- return ((Byte) value).longValue();
- }
- else if ((value instanceof String) || (value == null))
- {
- return Long.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeUnsignedInteger(buffer, (Long) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readUnsignedInteger(buffer);
- }
- },
-
- DECIMAL('D')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedByteLength() + EncodingUtils.encodedIntegerLength();
- }
-
- public Object toNativeValue(Object value)
- {
- if (value instanceof BigDecimal)
- {
- return (BigDecimal) value;
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to BigDecimal.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- BigDecimal bd = (BigDecimal) value;
-
- byte places = new Integer(bd.scale()).byteValue();
-
- int unscaled = bd.intValue();
-
- EncodingUtils.writeByte(buffer, places);
-
- EncodingUtils.writeInteger(buffer, unscaled);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- byte places = EncodingUtils.readByte(buffer);
-
- int unscaled = EncodingUtils.readInteger(buffer);
-
- BigDecimal bd = new BigDecimal(unscaled);
-
- return bd.setScale(places);
- }
- },
-
- TIMESTAMP('T')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedLongLength();
- }
-
- public Object toNativeValue(Object value)
- {
- if (value instanceof Long)
- {
- return (Long) value;
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to timestamp.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLong(buffer, (Long) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLong(buffer);
- }
- },
-
- /**
- * Implements the field table type. The native value of a field table type will be an instance of
- * {@link FieldTable}, which itself may contain name/value pairs encoded as {@link AMQTypedValue}s.
- */
- FIELD_TABLE('F')
- {
- /**
- * Calculates the size of an instance of the type in bytes.
- *
- * @param value An instance of the type.
- *
- * @return The size of the instance of the type in bytes.
- */
- public int getEncodingSize(Object value)
- {
- // Ensure that the value is a FieldTable.
- if (!(value instanceof FieldTable))
- {
- throw new IllegalArgumentException("Value is not a FieldTable.");
- }
-
- FieldTable ftValue = (FieldTable) value;
-
- // Loop over all name/value pairs adding up size of each. FieldTable itself keeps track of its encoded
- // size as entries are added, so no need to loop over all explicitly.
- // EncodingUtils calculation of the encoded field table lenth, will include 4 bytes for its 'size' field.
- return EncodingUtils.encodedFieldTableLength(ftValue);
- }
-
- /**
- * Converts an instance of the type to an equivalent Java native representation.
- *
- * @param value An instance of the type.
- *
- * @return An equivalent Java native representation.
- */
- public Object toNativeValue(Object value)
- {
- // Ensure that the value is a FieldTable.
- if (!(value instanceof FieldTable))
- {
- throw new IllegalArgumentException("Value is not a FieldTable.");
- }
-
- return (FieldTable) value;
- }
-
- /**
- * Writes an instance of the type to a specified byte buffer.
- *
- * @param value An instance of the type.
- * @param buffer The byte buffer to write it to.
- */
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- // Ensure that the value is a FieldTable.
- if (!(value instanceof FieldTable))
- {
- throw new IllegalArgumentException("Value is not a FieldTable.");
- }
-
- FieldTable ftValue = (FieldTable) value;
-
- // Loop over all name/values writing out into buffer.
- ftValue.writeToBuffer(buffer);
- }
-
- /**
- * Reads an instance of the type from a specified byte buffer.
- *
- * @param buffer The byte buffer to write it to.
- *
- * @return An instance of the type.
- */
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- try
- {
- // Read size of field table then all name/value pairs.
- return EncodingUtils.readFieldTable(buffer);
- }
- catch (AMQFrameDecodingException e)
- {
- throw new IllegalArgumentException("Unable to read field table from buffer.", e);
- }
- }
- },
-
- VOID('V')
- {
- public int getEncodingSize(Object value)
- {
- return 0;
- }
-
- public Object toNativeValue(Object value)
- {
- if (value == null)
- {
- return null;
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to null String.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- { }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return null;
- }
- },
-
- BINARY('x')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedLongstrLength((byte[]) value);
- }
-
- public Object toNativeValue(Object value)
- {
- if ((value instanceof byte[]) || (value == null))
- {
- return value;
- }
- else
- {
- throw new IllegalArgumentException("Value: " + value + " (" + value.getClass().getName()
- + ") cannot be converted to byte[]");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLongstr(buffer, (byte[]) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLongstr(buffer);
- }
- },
-
- ASCII_STRING('c')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedLongStringLength((String) value);
- }
-
- public String toNativeValue(Object value)
- {
- if (value != null)
- {
- return value.toString();
- }
- else
- {
- throw new NullPointerException("Cannot convert: null to String.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLongString(buffer);
- }
- },
-
- WIDE_STRING('C')
- {
- public int getEncodingSize(Object value)
- {
- // FIXME: use proper charset encoder
- return EncodingUtils.encodedLongStringLength((String) value);
- }
-
- public String toNativeValue(Object value)
- {
- if (value != null)
- {
- return value.toString();
- }
- else
- {
- throw new NullPointerException("Cannot convert: null to String.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLongString(buffer);
- }
- },
-
- BOOLEAN('t')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedBooleanLength();
- }
-
- public Object toNativeValue(Object value)
- {
- if (value instanceof Boolean)
- {
- return (Boolean) value;
- }
- else if ((value instanceof String) || (value == null))
- {
- return Boolean.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to boolean.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeBoolean(buffer, (Boolean) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readBoolean(buffer);
- }
- },
-
- ASCII_CHARACTER('k')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedCharLength();
- }
-
- public Character toNativeValue(Object value)
- {
- if (value instanceof Character)
- {
- return (Character) value;
- }
- else if (value == null)
- {
- throw new NullPointerException("Cannot convert null into char");
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to char.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeChar(buffer, (Character) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readChar(buffer);
- }
- },
-
- BYTE('b')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedByteLength();
- }
-
- public Byte toNativeValue(Object value)
- {
- if (value instanceof Byte)
- {
- return (Byte) value;
- }
- else if ((value instanceof String) || (value == null))
- {
- return Byte.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to byte.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeByte(buffer, (Byte) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readByte(buffer);
- }
- },
-
- SHORT('s')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedShortLength();
- }
-
- public Short toNativeValue(Object value)
- {
- if (value instanceof Short)
- {
- return (Short) value;
- }
- else if (value instanceof Byte)
- {
- return ((Byte) value).shortValue();
- }
- else if ((value instanceof String) || (value == null))
- {
- return Short.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to short.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeShort(buffer, (Short) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readShort(buffer);
- }
- },
-
- INT('I')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedIntegerLength();
- }
-
- public Integer toNativeValue(Object value)
- {
- if (value instanceof Integer)
- {
- return (Integer) value;
- }
- else if (value instanceof Short)
- {
- return ((Short) value).intValue();
- }
- else if (value instanceof Byte)
- {
- return ((Byte) value).intValue();
- }
- else if ((value instanceof String) || (value == null))
- {
- return Integer.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeInteger(buffer, (Integer) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readInteger(buffer);
- }
- },
-
- LONG('l')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedLongLength();
- }
-
- public Object toNativeValue(Object value)
- {
- if (value instanceof Long)
- {
- return (Long) value;
- }
- else if (value instanceof Integer)
- {
- return ((Integer) value).longValue();
- }
- else if (value instanceof Short)
- {
- return ((Short) value).longValue();
- }
- else if (value instanceof Byte)
- {
- return ((Byte) value).longValue();
- }
- else if ((value instanceof String) || (value == null))
- {
- return Long.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to long.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeLong(buffer, (Long) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readLong(buffer);
- }
- },
-
- FLOAT('f')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedFloatLength();
- }
-
- public Float toNativeValue(Object value)
- {
- if (value instanceof Float)
- {
- return (Float) value;
- }
- else if ((value instanceof String) || (value == null))
- {
- return Float.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to float.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeFloat(buffer, (Float) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readFloat(buffer);
- }
- },
-
- DOUBLE('d')
- {
- public int getEncodingSize(Object value)
- {
- return EncodingUtils.encodedDoubleLength();
- }
-
- public Double toNativeValue(Object value)
- {
- if (value instanceof Double)
- {
- return (Double) value;
- }
- else if (value instanceof Float)
- {
- return ((Float) value).doubleValue();
- }
- else if ((value instanceof String) || (value == null))
- {
- return Double.valueOf((String) value);
- }
- else
- {
- throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
- + ") to double.");
- }
- }
-
- public void writeValueImpl(Object value, ByteBuffer buffer)
- {
- EncodingUtils.writeDouble(buffer, (Double) value);
- }
-
- public Object readValueFromBuffer(ByteBuffer buffer)
- {
- return EncodingUtils.readDouble(buffer);
- }
- };
-
- /** Holds the defined one byte identifier for the type. */
- private final byte _identifier;
-
- /**
- * Creates an instance of an AMQP type from its defined one byte identifier.
- *
- * @param identifier The one byte identifier for the type.
- */
- AMQType(char identifier)
- {
- _identifier = (byte) identifier;
- }
-
- /**
- * Extracts the byte identifier for the typ.
- *
- * @return The byte identifier for the typ.
- */
- public final byte identifier()
- {
- return _identifier;
- }
-
- /**
- * Calculates the size of an instance of the type in bytes.
- *
- * @param value An instance of the type.
- *
- * @return The size of the instance of the type in bytes.
- */
- public abstract int getEncodingSize(Object value);
-
- /**
- * Converts an instance of the type to an equivalent Java native representation.
- *
- * @param value An instance of the type.
- *
- * @return An equivalent Java native representation.
- */
- public abstract Object toNativeValue(Object value);
-
- /**
- * Converts an instance of the type to an equivalent Java native representation, packaged as an
- * {@link AMQTypedValue} tagged with its AMQP type.
- *
- * @param value An instance of the type.
- *
- * @return An equivalent Java native representation, tagged with its AMQP type.
- */
- public AMQTypedValue asTypedValue(Object value)
- {
- return new AMQTypedValue(this, toNativeValue(value));
- }
-
- /**
- * Writes an instance of the type to a specified byte buffer, preceded by its one byte identifier. As the type and
- * value are both written, this provides a fully encoded description of a parameters type and value.
- *
- * @param value An instance of the type.
- * @param buffer The byte buffer to write it to.
- */
- public void writeToBuffer(Object value, ByteBuffer buffer)
- {
- buffer.put(identifier());
- writeValueImpl(value, buffer);
- }
-
- /**
- * Writes an instance of the type to a specified byte buffer.
- *
- * @param value An instance of the type.
- * @param buffer The byte buffer to write it to.
- */
- abstract void writeValueImpl(Object value, ByteBuffer buffer);
-
- /**
- * Reads an instance of the type from a specified byte buffer.
- *
- * @param buffer The byte buffer to write it to.
- *
- * @return An instance of the type.
- */
- abstract Object readValueFromBuffer(ByteBuffer buffer);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+import java.math.BigDecimal;
+
+/**
+ * AMQType is a type that represents the different possible AMQP field table types. It provides operations for each
+ * of the types to perform tasks such as calculating the size of an instance of the type, converting types between AMQP
+ * and Java native types, and reading and writing instances of AMQP types in binary formats to and from byte buffers.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Get the equivalent one byte identifier for a type.
+ * <tr><td> Calculate the size of an instance of an AMQP parameter type. <td> {@link EncodingUtils}
+ * <tr><td> Convert an instance of an AMQP parameter into a compatable Java object tagged with its AMQP type.
+ * <td> {@link AMQTypedValue}
+ * <tr><td> Write an instance of an AMQP parameter type to a byte buffer. <td> {@link EncodingUtils}
+ * <tr><td> Read an instance of an AMQP parameter from a byte buffer. <td> {@link EncodingUtils}
+ * </table>
+ */
+public enum AMQType
+{
+ LONG_STRING('S')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedLongStringLength((String) value);
+ }
+
+ public String toNativeValue(Object value)
+ {
+ if (value != null)
+ {
+ return value.toString();
+ }
+ else
+ {
+ throw new NullPointerException("Cannot convert: null to String.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLongStringBytes(buffer, (String) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLongString(buffer);
+ }
+ },
+
+ INTEGER('i')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.unsignedIntegerLength();
+ }
+
+ public Long toNativeValue(Object value)
+ {
+ if (value instanceof Long)
+ {
+ return (Long) value;
+ }
+ else if (value instanceof Integer)
+ {
+ return ((Integer) value).longValue();
+ }
+ else if (value instanceof Short)
+ {
+ return ((Short) value).longValue();
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte) value).longValue();
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Long.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeUnsignedInteger(buffer, (Long) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readUnsignedInteger(buffer);
+ }
+ },
+
+ DECIMAL('D')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedByteLength() + EncodingUtils.encodedIntegerLength();
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if (value instanceof BigDecimal)
+ {
+ return (BigDecimal) value;
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to BigDecimal.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ BigDecimal bd = (BigDecimal) value;
+
+ byte places = new Integer(bd.scale()).byteValue();
+
+ int unscaled = bd.intValue();
+
+ EncodingUtils.writeByte(buffer, places);
+
+ EncodingUtils.writeInteger(buffer, unscaled);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ byte places = EncodingUtils.readByte(buffer);
+
+ int unscaled = EncodingUtils.readInteger(buffer);
+
+ BigDecimal bd = new BigDecimal(unscaled);
+
+ return bd.setScale(places);
+ }
+ },
+
+ TIMESTAMP('T')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedLongLength();
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if (value instanceof Long)
+ {
+ return (Long) value;
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to timestamp.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLong(buffer, (Long) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLong(buffer);
+ }
+ },
+
+ /**
+ * Implements the field table type. The native value of a field table type will be an instance of
+ * {@link FieldTable}, which itself may contain name/value pairs encoded as {@link AMQTypedValue}s.
+ */
+ FIELD_TABLE('F')
+ {
+ /**
+ * Calculates the size of an instance of the type in bytes.
+ *
+ * @param value An instance of the type.
+ *
+ * @return The size of the instance of the type in bytes.
+ */
+ public int getEncodingSize(Object value)
+ {
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ FieldTable ftValue = (FieldTable) value;
+
+ // Loop over all name/value pairs adding up size of each. FieldTable itself keeps track of its encoded
+ // size as entries are added, so no need to loop over all explicitly.
+ // EncodingUtils calculation of the encoded field table lenth, will include 4 bytes for its 'size' field.
+ return EncodingUtils.encodedFieldTableLength(ftValue);
+ }
+
+ /**
+ * Converts an instance of the type to an equivalent Java native representation.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation.
+ */
+ public Object toNativeValue(Object value)
+ {
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ return (FieldTable) value;
+ }
+
+ /**
+ * Writes an instance of the type to a specified byte buffer.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ // Ensure that the value is a FieldTable.
+ if (!(value instanceof FieldTable))
+ {
+ throw new IllegalArgumentException("Value is not a FieldTable.");
+ }
+
+ FieldTable ftValue = (FieldTable) value;
+
+ // Loop over all name/values writing out into buffer.
+ ftValue.writeToBuffer(buffer);
+ }
+
+ /**
+ * Reads an instance of the type from a specified byte buffer.
+ *
+ * @param buffer The byte buffer to write it to.
+ *
+ * @return An instance of the type.
+ */
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ try
+ {
+ // Read size of field table then all name/value pairs.
+ return EncodingUtils.readFieldTable(buffer);
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ throw new IllegalArgumentException("Unable to read field table from buffer.", e);
+ }
+ }
+ },
+
+ VOID('V')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return 0;
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to null String.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ { }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return null;
+ }
+ },
+
+ BINARY('x')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedLongstrLength((byte[]) value);
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if ((value instanceof byte[]) || (value == null))
+ {
+ return value;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Value: " + value + " (" + value.getClass().getName()
+ + ") cannot be converted to byte[]");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLongstr(buffer, (byte[]) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLongstr(buffer);
+ }
+ },
+
+ ASCII_STRING('c')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedLongStringLength((String) value);
+ }
+
+ public String toNativeValue(Object value)
+ {
+ if (value != null)
+ {
+ return value.toString();
+ }
+ else
+ {
+ throw new NullPointerException("Cannot convert: null to String.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLongStringBytes(buffer, (String) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLongString(buffer);
+ }
+ },
+
+ WIDE_STRING('C')
+ {
+ public int getEncodingSize(Object value)
+ {
+ // FIXME: use proper charset encoder
+ return EncodingUtils.encodedLongStringLength((String) value);
+ }
+
+ public String toNativeValue(Object value)
+ {
+ if (value != null)
+ {
+ return value.toString();
+ }
+ else
+ {
+ throw new NullPointerException("Cannot convert: null to String.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLongStringBytes(buffer, (String) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLongString(buffer);
+ }
+ },
+
+ BOOLEAN('t')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedBooleanLength();
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if (value instanceof Boolean)
+ {
+ return (Boolean) value;
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Boolean.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to boolean.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeBoolean(buffer, (Boolean) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readBoolean(buffer);
+ }
+ },
+
+ ASCII_CHARACTER('k')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedCharLength();
+ }
+
+ public Character toNativeValue(Object value)
+ {
+ if (value instanceof Character)
+ {
+ return (Character) value;
+ }
+ else if (value == null)
+ {
+ throw new NullPointerException("Cannot convert null into char");
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to char.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeChar(buffer, (Character) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readChar(buffer);
+ }
+ },
+
+ BYTE('b')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedByteLength();
+ }
+
+ public Byte toNativeValue(Object value)
+ {
+ if (value instanceof Byte)
+ {
+ return (Byte) value;
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Byte.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to byte.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeByte(buffer, (Byte) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readByte(buffer);
+ }
+ },
+
+ SHORT('s')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedShortLength();
+ }
+
+ public Short toNativeValue(Object value)
+ {
+ if (value instanceof Short)
+ {
+ return (Short) value;
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte) value).shortValue();
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Short.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to short.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeShort(buffer, (Short) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readShort(buffer);
+ }
+ },
+
+ INT('I')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedIntegerLength();
+ }
+
+ public Integer toNativeValue(Object value)
+ {
+ if (value instanceof Integer)
+ {
+ return (Integer) value;
+ }
+ else if (value instanceof Short)
+ {
+ return ((Short) value).intValue();
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte) value).intValue();
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Integer.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName() + ") to int.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeInteger(buffer, (Integer) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readInteger(buffer);
+ }
+ },
+
+ LONG('l')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedLongLength();
+ }
+
+ public Object toNativeValue(Object value)
+ {
+ if (value instanceof Long)
+ {
+ return (Long) value;
+ }
+ else if (value instanceof Integer)
+ {
+ return ((Integer) value).longValue();
+ }
+ else if (value instanceof Short)
+ {
+ return ((Short) value).longValue();
+ }
+ else if (value instanceof Byte)
+ {
+ return ((Byte) value).longValue();
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Long.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to long.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeLong(buffer, (Long) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readLong(buffer);
+ }
+ },
+
+ FLOAT('f')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedFloatLength();
+ }
+
+ public Float toNativeValue(Object value)
+ {
+ if (value instanceof Float)
+ {
+ return (Float) value;
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Float.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to float.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeFloat(buffer, (Float) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readFloat(buffer);
+ }
+ },
+
+ DOUBLE('d')
+ {
+ public int getEncodingSize(Object value)
+ {
+ return EncodingUtils.encodedDoubleLength();
+ }
+
+ public Double toNativeValue(Object value)
+ {
+ if (value instanceof Double)
+ {
+ return (Double) value;
+ }
+ else if (value instanceof Float)
+ {
+ return ((Float) value).doubleValue();
+ }
+ else if ((value instanceof String) || (value == null))
+ {
+ return Double.valueOf((String) value);
+ }
+ else
+ {
+ throw new NumberFormatException("Cannot convert: " + value + "(" + value.getClass().getName()
+ + ") to double.");
+ }
+ }
+
+ public void writeValueImpl(Object value, ByteBuffer buffer)
+ {
+ EncodingUtils.writeDouble(buffer, (Double) value);
+ }
+
+ public Object readValueFromBuffer(ByteBuffer buffer)
+ {
+ return EncodingUtils.readDouble(buffer);
+ }
+ };
+
+ /** Holds the defined one byte identifier for the type. */
+ private final byte _identifier;
+
+ /**
+ * Creates an instance of an AMQP type from its defined one byte identifier.
+ *
+ * @param identifier The one byte identifier for the type.
+ */
+ AMQType(char identifier)
+ {
+ _identifier = (byte) identifier;
+ }
+
+ /**
+ * Extracts the byte identifier for the typ.
+ *
+ * @return The byte identifier for the typ.
+ */
+ public final byte identifier()
+ {
+ return _identifier;
+ }
+
+ /**
+ * Calculates the size of an instance of the type in bytes.
+ *
+ * @param value An instance of the type.
+ *
+ * @return The size of the instance of the type in bytes.
+ */
+ public abstract int getEncodingSize(Object value);
+
+ /**
+ * Converts an instance of the type to an equivalent Java native representation.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation.
+ */
+ public abstract Object toNativeValue(Object value);
+
+ /**
+ * Converts an instance of the type to an equivalent Java native representation, packaged as an
+ * {@link AMQTypedValue} tagged with its AMQP type.
+ *
+ * @param value An instance of the type.
+ *
+ * @return An equivalent Java native representation, tagged with its AMQP type.
+ */
+ public AMQTypedValue asTypedValue(Object value)
+ {
+ return new AMQTypedValue(this, toNativeValue(value));
+ }
+
+ /**
+ * Writes an instance of the type to a specified byte buffer, preceded by its one byte identifier. As the type and
+ * value are both written, this provides a fully encoded description of a parameters type and value.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
+ public void writeToBuffer(Object value, ByteBuffer buffer)
+ {
+ buffer.put(identifier());
+ writeValueImpl(value, buffer);
+ }
+
+ /**
+ * Writes an instance of the type to a specified byte buffer.
+ *
+ * @param value An instance of the type.
+ * @param buffer The byte buffer to write it to.
+ */
+ abstract void writeValueImpl(Object value, ByteBuffer buffer);
+
+ /**
+ * Reads an instance of the type from a specified byte buffer.
+ *
+ * @param buffer The byte buffer to write it to.
+ *
+ * @return An instance of the type.
+ */
+ abstract Object readValueFromBuffer(ByteBuffer buffer);
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java
index 1419dd75b1..a16e137466 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java
@@ -1,48 +1,48 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.framing;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class AMQTypeMap
-{
- public static Map<Byte, AMQType> _reverseTypeMap = new HashMap<Byte, AMQType>();
-
- static
- {
- for(AMQType type : AMQType.values())
- {
- _reverseTypeMap.put(type.identifier(), type);
- }
- }
-
- public static AMQType getType(Byte identifier)
- {
- AMQType result = _reverseTypeMap.get(identifier);
- if (result == null) {
- throw new IllegalArgumentException
- ("no such type code: " + Integer.toHexString(identifier.intValue()));
- }
- return result;
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class AMQTypeMap
+{
+ public static Map<Byte, AMQType> _reverseTypeMap = new HashMap<Byte, AMQType>();
+
+ static
+ {
+ for(AMQType type : AMQType.values())
+ {
+ _reverseTypeMap.put(type.identifier(), type);
+ }
+ }
+
+ public static AMQType getType(Byte identifier)
+ {
+ AMQType result = _reverseTypeMap.get(identifier);
+ if (result == null) {
+ throw new IllegalArgumentException
+ ("no such type code: " + Integer.toHexString(identifier.intValue()));
+ }
+ return result;
+ }
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
index e5b1fad9a8..d6359baa0f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
@@ -1,96 +1,96 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-/**
- * AMQTypedValue combines together a native Java Object value, and an {@link AMQType}, as a fully typed AMQP parameter
- * value. It provides the ability to read and write fully typed parameters to and from byte buffers. It also provides
- * the ability to create such parameters from Java native value and a type tag or to extract the native value and type
- * from one.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Create a fully typed AMQP value from a native type and a type tag. <td> {@link AMQType}
- * <tr><td> Create a fully typed AMQP value from a binary representation in a byte buffer. <td> {@link AMQType}
- * <tr><td> Write a fully typed AMQP value to a binary representation in a byte buffer. <td> {@link AMQType}
- * <tr><td> Extract the type from a fully typed AMQP value.
- * <tr><td> Extract the value from a fully typed AMQP value.
- * </table>
- */
-public class AMQTypedValue
-{
- /** The type of the value. */
- private final AMQType _type;
-
- /** The Java native representation of the AMQP typed value. */
- private final Object _value;
-
- public AMQTypedValue(AMQType type, Object value)
- {
- if (type == null)
- {
- throw new NullPointerException("Cannot create a typed value with null type");
- }
-
- _type = type;
- _value = type.toNativeValue(value);
- }
-
- private AMQTypedValue(AMQType type, ByteBuffer buffer)
- {
- _type = type;
- _value = type.readValueFromBuffer(buffer);
- }
-
- public AMQType getType()
- {
- return _type;
- }
-
- public Object getValue()
- {
- return _value;
- }
-
- public void writeToBuffer(ByteBuffer buffer)
- {
- _type.writeToBuffer(_value, buffer);
- }
-
- public int getEncodingSize()
- {
- return _type.getEncodingSize(_value);
- }
-
- public static AMQTypedValue readFromBuffer(ByteBuffer buffer)
- {
- AMQType type = AMQTypeMap.getType(buffer.get());
-
- return new AMQTypedValue(type, buffer);
- }
-
- public String toString()
- {
- return "[" + getType() + ": " + getValue() + "]";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+/**
+ * AMQTypedValue combines together a native Java Object value, and an {@link AMQType}, as a fully typed AMQP parameter
+ * value. It provides the ability to read and write fully typed parameters to and from byte buffers. It also provides
+ * the ability to create such parameters from Java native value and a type tag or to extract the native value and type
+ * from one.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create a fully typed AMQP value from a native type and a type tag. <td> {@link AMQType}
+ * <tr><td> Create a fully typed AMQP value from a binary representation in a byte buffer. <td> {@link AMQType}
+ * <tr><td> Write a fully typed AMQP value to a binary representation in a byte buffer. <td> {@link AMQType}
+ * <tr><td> Extract the type from a fully typed AMQP value.
+ * <tr><td> Extract the value from a fully typed AMQP value.
+ * </table>
+ */
+public class AMQTypedValue
+{
+ /** The type of the value. */
+ private final AMQType _type;
+
+ /** The Java native representation of the AMQP typed value. */
+ private final Object _value;
+
+ public AMQTypedValue(AMQType type, Object value)
+ {
+ if (type == null)
+ {
+ throw new NullPointerException("Cannot create a typed value with null type");
+ }
+
+ _type = type;
+ _value = type.toNativeValue(value);
+ }
+
+ private AMQTypedValue(AMQType type, ByteBuffer buffer)
+ {
+ _type = type;
+ _value = type.readValueFromBuffer(buffer);
+ }
+
+ public AMQType getType()
+ {
+ return _type;
+ }
+
+ public Object getValue()
+ {
+ return _value;
+ }
+
+ public void writeToBuffer(ByteBuffer buffer)
+ {
+ _type.writeToBuffer(_value, buffer);
+ }
+
+ public int getEncodingSize()
+ {
+ return _type.getEncodingSize(_value);
+ }
+
+ public static AMQTypedValue readFromBuffer(ByteBuffer buffer)
+ {
+ AMQType type = AMQTypeMap.getType(buffer.get());
+
+ return new AMQTypedValue(type, buffer);
+ }
+
+ public String toString()
+ {
+ return "[" + getType() + ": " + getValue() + "]";
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/CommonContentHeaderProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/CommonContentHeaderProperties.java
index 6a608a8bff..7162c37062 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/CommonContentHeaderProperties.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/CommonContentHeaderProperties.java
@@ -1,81 +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.framing;
-
-public interface CommonContentHeaderProperties extends ContentHeaderProperties
-{
- AMQShortString getContentType();
-
- void setContentType(AMQShortString contentType);
-
- FieldTable getHeaders();
-
- void setHeaders(FieldTable headers);
-
- byte getDeliveryMode();
-
- void setDeliveryMode(byte deliveryMode);
-
- byte getPriority();
-
- void setPriority(byte priority);
-
- AMQShortString getCorrelationId();
-
- void setCorrelationId(AMQShortString correlationId);
-
- AMQShortString getReplyTo();
-
- void setReplyTo(AMQShortString replyTo);
-
- long getExpiration();
-
- void setExpiration(long expiration);
-
- AMQShortString getMessageId();
-
- void setMessageId(AMQShortString messageId);
-
- long getTimestamp();
-
- void setTimestamp(long timestamp);
-
- AMQShortString getType();
-
- void setType(AMQShortString type);
-
- AMQShortString getUserId();
-
- void setUserId(AMQShortString userId);
-
- AMQShortString getAppId();
-
- void setAppId(AMQShortString appId);
-
- AMQShortString getClusterId();
-
- void setClusterId(AMQShortString clusterId);
-
- AMQShortString getEncoding();
-
- void setEncoding(AMQShortString encoding);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing;
+
+public interface CommonContentHeaderProperties extends ContentHeaderProperties
+{
+ AMQShortString getContentType();
+
+ void setContentType(AMQShortString contentType);
+
+ FieldTable getHeaders();
+
+ void setHeaders(FieldTable headers);
+
+ byte getDeliveryMode();
+
+ void setDeliveryMode(byte deliveryMode);
+
+ byte getPriority();
+
+ void setPriority(byte priority);
+
+ AMQShortString getCorrelationId();
+
+ void setCorrelationId(AMQShortString correlationId);
+
+ AMQShortString getReplyTo();
+
+ void setReplyTo(AMQShortString replyTo);
+
+ long getExpiration();
+
+ void setExpiration(long expiration);
+
+ AMQShortString getMessageId();
+
+ void setMessageId(AMQShortString messageId);
+
+ long getTimestamp();
+
+ void setTimestamp(long timestamp);
+
+ AMQShortString getType();
+
+ void setType(AMQShortString type);
+
+ AMQShortString getUserId();
+
+ void setUserId(AMQShortString userId);
+
+ AMQShortString getAppId();
+
+ void setAppId(AMQShortString appId);
+
+ AMQShortString getClusterId();
+
+ void setClusterId(AMQShortString clusterId);
+
+ AMQShortString getEncoding();
+
+ void setEncoding(AMQShortString encoding);
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
index f8cf3f3011..bd763599b0 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/SmallCompositeAMQDataBlock.java
@@ -1,98 +1,98 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-public class SmallCompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock
-{
- private AMQDataBlock _firstFrame;
-
- private AMQDataBlock _block;
-
- public SmallCompositeAMQDataBlock(AMQDataBlock block)
- {
- _block = block;
- }
-
- /**
- * The encoded block will be logically first before the AMQDataBlocks which are encoded
- * into the buffer afterwards.
- * @param encodedBlock already-encoded data
- * @param block a block to be encoded.
- */
- public SmallCompositeAMQDataBlock(AMQDataBlock encodedBlock, AMQDataBlock block)
- {
- this(block);
- _firstFrame = encodedBlock;
- }
-
- public AMQDataBlock getBlock()
- {
- return _block;
- }
-
- public AMQDataBlock getFirstFrame()
- {
- return _firstFrame;
- }
-
- public long getSize()
- {
- long frameSize = _block.getSize();
-
- if (_firstFrame != null)
- {
-
- frameSize += _firstFrame.getSize();
- }
- return frameSize;
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- if (_firstFrame != null)
- {
- _firstFrame.writePayload(buffer);
- }
- _block.writePayload(buffer);
-
- }
-
- public String toString()
- {
- if (_block == null)
- {
- return "No blocks contained in composite frame";
- }
- else
- {
- StringBuilder buf = new StringBuilder(this.getClass().getName());
- buf.append("{encodedBlock=").append(_firstFrame);
-
- buf.append(" _block=[").append(_block.toString()).append("]");
-
- buf.append("}");
- return buf.toString();
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+public class SmallCompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock
+{
+ private AMQDataBlock _firstFrame;
+
+ private AMQDataBlock _block;
+
+ public SmallCompositeAMQDataBlock(AMQDataBlock block)
+ {
+ _block = block;
+ }
+
+ /**
+ * The encoded block will be logically first before the AMQDataBlocks which are encoded
+ * into the buffer afterwards.
+ * @param encodedBlock already-encoded data
+ * @param block a block to be encoded.
+ */
+ public SmallCompositeAMQDataBlock(AMQDataBlock encodedBlock, AMQDataBlock block)
+ {
+ this(block);
+ _firstFrame = encodedBlock;
+ }
+
+ public AMQDataBlock getBlock()
+ {
+ return _block;
+ }
+
+ public AMQDataBlock getFirstFrame()
+ {
+ return _firstFrame;
+ }
+
+ public long getSize()
+ {
+ long frameSize = _block.getSize();
+
+ if (_firstFrame != null)
+ {
+
+ frameSize += _firstFrame.getSize();
+ }
+ return frameSize;
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ if (_firstFrame != null)
+ {
+ _firstFrame.writePayload(buffer);
+ }
+ _block.writePayload(buffer);
+
+ }
+
+ public String toString()
+ {
+ if (_block == null)
+ {
+ return "No blocks contained in composite frame";
+ }
+ else
+ {
+ StringBuilder buf = new StringBuilder(this.getClass().getName());
+ buf.append("{encodedBlock=").append(_firstFrame);
+
+ buf.append(" _block=[").append(_block.toString()).append("]");
+
+ buf.append("}");
+ return buf.toString();
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
index 516d0c569c..76c154581d 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java
@@ -1,198 +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.framing;
-
-import org.apache.mina.common.ByteBuffer;
-
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class VersionSpecificRegistry
-{
- private static final Logger _log = LoggerFactory.getLogger(VersionSpecificRegistry.class);
-
- private final byte _protocolMajorVersion;
- private final byte _protocolMinorVersion;
-
- private static final int DEFAULT_MAX_CLASS_ID = 200;
- private static final int DEFAULT_MAX_METHOD_ID = 50;
-
- private AMQMethodBodyInstanceFactory[][] _registry = new AMQMethodBodyInstanceFactory[DEFAULT_MAX_CLASS_ID][];
-
- private ProtocolVersionMethodConverter _protocolVersionConverter;
-
- public VersionSpecificRegistry(byte major, byte minor)
- {
- _protocolMajorVersion = major;
- _protocolMinorVersion = minor;
-
- _protocolVersionConverter = loadProtocolVersionConverters(major, minor);
- }
-
- private static ProtocolVersionMethodConverter loadProtocolVersionConverters(byte protocolMajorVersion,
- byte protocolMinorVersion)
- {
- try
- {
- Class<ProtocolVersionMethodConverter> versionMethodConverterClass =
- (Class<ProtocolVersionMethodConverter>) Class.forName("org.apache.qpid.framing.MethodConverter_"
- + protocolMajorVersion + "_" + protocolMinorVersion);
-
- return versionMethodConverterClass.newInstance();
-
- }
- catch (ClassNotFoundException e)
- {
- _log.warn("Could not find protocol conversion classes for " + protocolMajorVersion + "-" + protocolMinorVersion);
- if (protocolMinorVersion != 0)
- {
- protocolMinorVersion--;
-
- return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
- }
- else if (protocolMajorVersion != 0)
- {
- protocolMajorVersion--;
-
- return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
- }
- else
- {
- return null;
- }
-
- }
- catch (IllegalAccessException e)
- {
- throw new IllegalStateException("Unable to load protocol version converter: ", e);
- }
- catch (InstantiationException e)
- {
- throw new IllegalStateException("Unable to load protocol version converter: ", e);
- }
- }
-
- public byte getProtocolMajorVersion()
- {
- return _protocolMajorVersion;
- }
-
- public byte getProtocolMinorVersion()
- {
- return _protocolMinorVersion;
- }
-
- public AMQMethodBodyInstanceFactory getMethodBody(final short classID, final short methodID)
- {
- try
- {
- return _registry[classID][methodID];
- }
- catch (IndexOutOfBoundsException e)
- {
- return null;
- }
- catch (NullPointerException e)
- {
- return null;
- }
- }
-
- public void registerMethod(final short classID, final short methodID, final AMQMethodBodyInstanceFactory instanceFactory)
- {
- if (_registry.length <= classID)
- {
- AMQMethodBodyInstanceFactory[][] oldRegistry = _registry;
- _registry = new AMQMethodBodyInstanceFactory[classID + 1][];
- System.arraycopy(oldRegistry, 0, _registry, 0, oldRegistry.length);
- }
-
- if (_registry[classID] == null)
- {
- _registry[classID] =
- new AMQMethodBodyInstanceFactory[(methodID > DEFAULT_MAX_METHOD_ID) ? (methodID + 1)
- : (DEFAULT_MAX_METHOD_ID + 1)];
- }
- else if (_registry[classID].length <= methodID)
- {
- AMQMethodBodyInstanceFactory[] oldMethods = _registry[classID];
- _registry[classID] = new AMQMethodBodyInstanceFactory[methodID + 1];
- System.arraycopy(oldMethods, 0, _registry[classID], 0, oldMethods.length);
- }
-
- _registry[classID][methodID] = instanceFactory;
-
- }
-
- public AMQMethodBody get(short classID, short methodID, ByteBuffer in, long size) throws AMQFrameDecodingException
- {
- AMQMethodBodyInstanceFactory bodyFactory;
- try
- {
- bodyFactory = _registry[classID][methodID];
- }
- catch (NullPointerException e)
- {
- throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
- + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
- + " method " + methodID + ".", e);
- }
- catch (IndexOutOfBoundsException e)
- {
- if (classID >= _registry.length)
- {
- throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
- + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
- + " method " + methodID + ".", e);
-
- }
- else
- {
- throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
- + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
- + " method " + methodID + ".", e);
-
- }
- }
-
- if (bodyFactory == null)
- {
- throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
- + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
- + " method " + methodID + ".", null);
- }
-
- return bodyFactory.newInstance( in, size);
-
- }
-
- public ProtocolVersionMethodConverter getProtocolVersionMethodConverter()
- {
- return _protocolVersionConverter;
- }
-
- public void configure()
- {
- _protocolVersionConverter.configure();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VersionSpecificRegistry
+{
+ private static final Logger _log = LoggerFactory.getLogger(VersionSpecificRegistry.class);
+
+ private final byte _protocolMajorVersion;
+ private final byte _protocolMinorVersion;
+
+ private static final int DEFAULT_MAX_CLASS_ID = 200;
+ private static final int DEFAULT_MAX_METHOD_ID = 50;
+
+ private AMQMethodBodyInstanceFactory[][] _registry = new AMQMethodBodyInstanceFactory[DEFAULT_MAX_CLASS_ID][];
+
+ private ProtocolVersionMethodConverter _protocolVersionConverter;
+
+ public VersionSpecificRegistry(byte major, byte minor)
+ {
+ _protocolMajorVersion = major;
+ _protocolMinorVersion = minor;
+
+ _protocolVersionConverter = loadProtocolVersionConverters(major, minor);
+ }
+
+ private static ProtocolVersionMethodConverter loadProtocolVersionConverters(byte protocolMajorVersion,
+ byte protocolMinorVersion)
+ {
+ try
+ {
+ Class<ProtocolVersionMethodConverter> versionMethodConverterClass =
+ (Class<ProtocolVersionMethodConverter>) Class.forName("org.apache.qpid.framing.MethodConverter_"
+ + protocolMajorVersion + "_" + protocolMinorVersion);
+
+ return versionMethodConverterClass.newInstance();
+
+ }
+ catch (ClassNotFoundException e)
+ {
+ _log.warn("Could not find protocol conversion classes for " + protocolMajorVersion + "-" + protocolMinorVersion);
+ if (protocolMinorVersion != 0)
+ {
+ protocolMinorVersion--;
+
+ return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
+ }
+ else if (protocolMajorVersion != 0)
+ {
+ protocolMajorVersion--;
+
+ return loadProtocolVersionConverters(protocolMajorVersion, protocolMinorVersion);
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new IllegalStateException("Unable to load protocol version converter: ", e);
+ }
+ catch (InstantiationException e)
+ {
+ throw new IllegalStateException("Unable to load protocol version converter: ", e);
+ }
+ }
+
+ public byte getProtocolMajorVersion()
+ {
+ return _protocolMajorVersion;
+ }
+
+ public byte getProtocolMinorVersion()
+ {
+ return _protocolMinorVersion;
+ }
+
+ public AMQMethodBodyInstanceFactory getMethodBody(final short classID, final short methodID)
+ {
+ try
+ {
+ return _registry[classID][methodID];
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ return null;
+ }
+ catch (NullPointerException e)
+ {
+ return null;
+ }
+ }
+
+ public void registerMethod(final short classID, final short methodID, final AMQMethodBodyInstanceFactory instanceFactory)
+ {
+ if (_registry.length <= classID)
+ {
+ AMQMethodBodyInstanceFactory[][] oldRegistry = _registry;
+ _registry = new AMQMethodBodyInstanceFactory[classID + 1][];
+ System.arraycopy(oldRegistry, 0, _registry, 0, oldRegistry.length);
+ }
+
+ if (_registry[classID] == null)
+ {
+ _registry[classID] =
+ new AMQMethodBodyInstanceFactory[(methodID > DEFAULT_MAX_METHOD_ID) ? (methodID + 1)
+ : (DEFAULT_MAX_METHOD_ID + 1)];
+ }
+ else if (_registry[classID].length <= methodID)
+ {
+ AMQMethodBodyInstanceFactory[] oldMethods = _registry[classID];
+ _registry[classID] = new AMQMethodBodyInstanceFactory[methodID + 1];
+ System.arraycopy(oldMethods, 0, _registry[classID], 0, oldMethods.length);
+ }
+
+ _registry[classID][methodID] = instanceFactory;
+
+ }
+
+ public AMQMethodBody get(short classID, short methodID, ByteBuffer in, long size) throws AMQFrameDecodingException
+ {
+ AMQMethodBodyInstanceFactory bodyFactory;
+ try
+ {
+ bodyFactory = _registry[classID][methodID];
+ }
+ catch (NullPointerException e)
+ {
+ throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
+ + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
+ + " method " + methodID + ".", e);
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ if (classID >= _registry.length)
+ {
+ throw new AMQFrameDecodingException(null, "Class " + classID + " unknown in AMQP version "
+ + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
+ + " method " + methodID + ".", e);
+
+ }
+ else
+ {
+ throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
+ + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
+ + " method " + methodID + ".", e);
+
+ }
+ }
+
+ if (bodyFactory == null)
+ {
+ throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version "
+ + _protocolMajorVersion + "-" + _protocolMinorVersion + " (while trying to decode class " + classID
+ + " method " + methodID + ".", null);
+ }
+
+ return bodyFactory.newInstance( in, size);
+
+ }
+
+ public ProtocolVersionMethodConverter getProtocolVersionMethodConverter()
+ {
+ return _protocolVersionConverter;
+ }
+
+ public void configure()
+ {
+ _protocolVersionConverter.configure();
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/AbstractMethodConverter.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/AbstractMethodConverter.java
index 1c335f3036..1d7c05e9cc 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/AbstractMethodConverter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/AbstractMethodConverter.java
@@ -1,47 +1,47 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.abstraction;
-
-public abstract class AbstractMethodConverter implements ProtocolVersionMethodConverter
-{
- private final byte _protocolMajorVersion;
-
-
- private final byte _protocolMinorVersion;
-
- public AbstractMethodConverter(byte major, byte minor)
- {
- _protocolMajorVersion = major;
- _protocolMinorVersion = minor;
- }
-
-
- public final byte getProtocolMajorVersion()
- {
- return _protocolMajorVersion;
- }
-
- public final byte getProtocolMinorVersion()
- {
- return _protocolMinorVersion;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.abstraction;
+
+public abstract class AbstractMethodConverter implements ProtocolVersionMethodConverter
+{
+ private final byte _protocolMajorVersion;
+
+
+ private final byte _protocolMinorVersion;
+
+ public AbstractMethodConverter(byte major, byte minor)
+ {
+ _protocolMajorVersion = major;
+ _protocolMinorVersion = minor;
+ }
+
+
+ public final byte getProtocolMajorVersion()
+ {
+ return _protocolMajorVersion;
+ }
+
+ public final byte getProtocolMinorVersion()
+ {
+ return _protocolMinorVersion;
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
index 6312e478a8..0695349f76 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ContentChunk.java
@@ -1,32 +1,32 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.abstraction;
-
-import org.apache.mina.common.ByteBuffer;
-
-public interface ContentChunk
-{
- int getSize();
- ByteBuffer getData();
-
- void reduceToFit();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.abstraction;
+
+import org.apache.mina.common.ByteBuffer;
+
+public interface ContentChunk
+{
+ int getSize();
+ ByteBuffer getData();
+
+ void reduceToFit();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfo.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfo.java
index 49c28bb06b..a96bdcc171 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfo.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfo.java
@@ -1,38 +1,38 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.framing.abstraction;
-
-import org.apache.qpid.framing.AMQShortString;
-
-public interface MessagePublishInfo
-{
-
- public AMQShortString getExchange();
-
- public void setExchange(AMQShortString exchange);
-
- public boolean isImmediate();
-
- public boolean isMandatory();
-
- public AMQShortString getRoutingKey();
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.framing.abstraction;
+
+import org.apache.qpid.framing.AMQShortString;
+
+public interface MessagePublishInfo
+{
+
+ public AMQShortString getExchange();
+
+ public void setExchange(AMQShortString exchange);
+
+ public boolean isImmediate();
+
+ public boolean isMandatory();
+
+ public AMQShortString getRoutingKey();
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfoConverter.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfoConverter.java
index 42e2f7ad97..01d1a8a17b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfoConverter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/MessagePublishInfoConverter.java
@@ -1,32 +1,32 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.abstraction;
-
-import org.apache.qpid.framing.AMQMethodBody;
-
-
-public interface MessagePublishInfoConverter
-{
- public MessagePublishInfo convertToInfo(AMQMethodBody body);
- public AMQMethodBody convertToBody(MessagePublishInfo info);
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.abstraction;
+
+import org.apache.qpid.framing.AMQMethodBody;
+
+
+public interface MessagePublishInfoConverter
+{
+ public MessagePublishInfo convertToInfo(AMQMethodBody body);
+ public AMQMethodBody convertToBody(MessagePublishInfo info);
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
index 99588a0908..0a1cedc4e6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/abstraction/ProtocolVersionMethodConverter.java
@@ -1,32 +1,32 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.abstraction;
-
-import org.apache.qpid.framing.AMQBody;
-
-public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter
-{
- AMQBody convertToBody(ContentChunk contentBody);
- ContentChunk convertToContentChunk(AMQBody body);
-
- void configure();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.abstraction;
+
+import org.apache.qpid.framing.AMQBody;
+
+public interface ProtocolVersionMethodConverter extends MessagePublishInfoConverter
+{
+ AMQBody convertToBody(ContentChunk contentBody);
+ ContentChunk convertToContentChunk(AMQBody body);
+
+ void configure();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/AMQMethodBody_0_9.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/AMQMethodBody_0_9.java
index 3c5cb74773..948f5baaf6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/AMQMethodBody_0_9.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/AMQMethodBody_0_9.java
@@ -1,209 +1,209 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.amqp_0_9;
-
-import org.apache.qpid.framing.EncodingUtils;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.Content;
-
-import org.apache.mina.common.ByteBuffer;
-
-public abstract class AMQMethodBody_0_9 extends org.apache.qpid.framing.AMQMethodBodyImpl
-{
-
- public byte getMajor()
- {
- return 0;
- }
-
- public byte getMinor()
- {
- return 9;
- }
-
- public int getSize()
- {
- return 2 + 2 + getBodySize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- EncodingUtils.writeUnsignedShort(buffer, getClazz());
- EncodingUtils.writeUnsignedShort(buffer, getMethod());
- writeMethodPayload(buffer);
- }
-
-
- protected byte readByte(ByteBuffer buffer)
- {
- return buffer.get();
- }
-
- protected AMQShortString readAMQShortString(ByteBuffer buffer)
- {
- return EncodingUtils.readAMQShortString(buffer);
- }
-
- protected int getSizeOf(AMQShortString string)
- {
- return EncodingUtils.encodedShortStringLength(string);
- }
-
- protected void writeByte(ByteBuffer buffer, byte b)
- {
- buffer.put(b);
- }
-
- protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string)
- {
- EncodingUtils.writeShortStringBytes(buffer, string);
- }
-
- protected int readInt(ByteBuffer buffer)
- {
- return buffer.getInt();
- }
-
- protected void writeInt(ByteBuffer buffer, int i)
- {
- buffer.putInt(i);
- }
-
- protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
- {
- return EncodingUtils.readFieldTable(buffer);
- }
-
- protected int getSizeOf(FieldTable table)
- {
- return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeFieldTable(ByteBuffer buffer, FieldTable table)
- {
- EncodingUtils.writeFieldTableBytes(buffer, table);
- }
-
- protected long readLong(ByteBuffer buffer)
- {
- return buffer.getLong();
- }
-
- protected void writeLong(ByteBuffer buffer, long l)
- {
- buffer.putLong(l);
- }
-
- protected int getSizeOf(byte[] response)
- {
- return (response == null) ? 4 :response.length + 4;
- }
-
- protected void writeBytes(ByteBuffer buffer, byte[] data)
- {
- EncodingUtils.writeBytes(buffer,data);
- }
-
- protected byte[] readBytes(ByteBuffer buffer)
- {
- return EncodingUtils.readBytes(buffer);
- }
-
- protected short readShort(ByteBuffer buffer)
- {
- return EncodingUtils.readShort(buffer);
- }
-
- protected void writeShort(ByteBuffer buffer, short s)
- {
- EncodingUtils.writeShort(buffer, s);
- }
-
- protected Content readContent(ByteBuffer buffer)
- {
- return null; //To change body of created methods use File | Settings | File Templates.
- }
-
- protected int getSizeOf(Content body)
- {
- return 0; //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeContent(ByteBuffer buffer, Content body)
- {
- //To change body of created methods use File | Settings | File Templates.
- }
-
- protected byte readBitfield(ByteBuffer buffer)
- {
- return readByte(buffer); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected int readUnsignedShort(ByteBuffer buffer)
- {
- return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeBitfield(ByteBuffer buffer, byte bitfield0)
- {
- buffer.put(bitfield0);
- }
-
- protected void writeUnsignedShort(ByteBuffer buffer, int s)
- {
- EncodingUtils.writeUnsignedShort(buffer, s);
- }
-
- protected long readUnsignedInteger(ByteBuffer buffer)
- {
- return buffer.getUnsignedInt();
- }
- protected void writeUnsignedInteger(ByteBuffer buffer, long i)
- {
- EncodingUtils.writeUnsignedInteger(buffer, i);
- }
-
-
- protected short readUnsignedByte(ByteBuffer buffer)
- {
- return buffer.getUnsigned();
- }
-
- protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte)
- {
- EncodingUtils.writeUnsignedByte(buffer, unsignedByte);
- }
-
- protected long readTimestamp(ByteBuffer buffer)
- {
- return EncodingUtils.readTimestamp(buffer);
- }
-
- protected void writeTimestamp(ByteBuffer buffer, long t)
- {
- EncodingUtils.writeTimestamp(buffer, t);
- }
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.amqp_0_9;
+
+import org.apache.qpid.framing.EncodingUtils;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.Content;
+
+import org.apache.mina.common.ByteBuffer;
+
+public abstract class AMQMethodBody_0_9 extends org.apache.qpid.framing.AMQMethodBodyImpl
+{
+
+ public byte getMajor()
+ {
+ return 0;
+ }
+
+ public byte getMinor()
+ {
+ return 9;
+ }
+
+ public int getSize()
+ {
+ return 2 + 2 + getBodySize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ EncodingUtils.writeUnsignedShort(buffer, getClazz());
+ EncodingUtils.writeUnsignedShort(buffer, getMethod());
+ writeMethodPayload(buffer);
+ }
+
+
+ protected byte readByte(ByteBuffer buffer)
+ {
+ return buffer.get();
+ }
+
+ protected AMQShortString readAMQShortString(ByteBuffer buffer)
+ {
+ return EncodingUtils.readAMQShortString(buffer);
+ }
+
+ protected int getSizeOf(AMQShortString string)
+ {
+ return EncodingUtils.encodedShortStringLength(string);
+ }
+
+ protected void writeByte(ByteBuffer buffer, byte b)
+ {
+ buffer.put(b);
+ }
+
+ protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, string);
+ }
+
+ protected int readInt(ByteBuffer buffer)
+ {
+ return buffer.getInt();
+ }
+
+ protected void writeInt(ByteBuffer buffer, int i)
+ {
+ buffer.putInt(i);
+ }
+
+ protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
+ {
+ return EncodingUtils.readFieldTable(buffer);
+ }
+
+ protected int getSizeOf(FieldTable table)
+ {
+ return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeFieldTable(ByteBuffer buffer, FieldTable table)
+ {
+ EncodingUtils.writeFieldTableBytes(buffer, table);
+ }
+
+ protected long readLong(ByteBuffer buffer)
+ {
+ return buffer.getLong();
+ }
+
+ protected void writeLong(ByteBuffer buffer, long l)
+ {
+ buffer.putLong(l);
+ }
+
+ protected int getSizeOf(byte[] response)
+ {
+ return (response == null) ? 4 :response.length + 4;
+ }
+
+ protected void writeBytes(ByteBuffer buffer, byte[] data)
+ {
+ EncodingUtils.writeBytes(buffer,data);
+ }
+
+ protected byte[] readBytes(ByteBuffer buffer)
+ {
+ return EncodingUtils.readBytes(buffer);
+ }
+
+ protected short readShort(ByteBuffer buffer)
+ {
+ return EncodingUtils.readShort(buffer);
+ }
+
+ protected void writeShort(ByteBuffer buffer, short s)
+ {
+ EncodingUtils.writeShort(buffer, s);
+ }
+
+ protected Content readContent(ByteBuffer buffer)
+ {
+ return null; //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected int getSizeOf(Content body)
+ {
+ return 0; //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeContent(ByteBuffer buffer, Content body)
+ {
+ //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected byte readBitfield(ByteBuffer buffer)
+ {
+ return readByte(buffer); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected int readUnsignedShort(ByteBuffer buffer)
+ {
+ return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeBitfield(ByteBuffer buffer, byte bitfield0)
+ {
+ buffer.put(bitfield0);
+ }
+
+ protected void writeUnsignedShort(ByteBuffer buffer, int s)
+ {
+ EncodingUtils.writeUnsignedShort(buffer, s);
+ }
+
+ protected long readUnsignedInteger(ByteBuffer buffer)
+ {
+ return buffer.getUnsignedInt();
+ }
+ protected void writeUnsignedInteger(ByteBuffer buffer, long i)
+ {
+ EncodingUtils.writeUnsignedInteger(buffer, i);
+ }
+
+
+ protected short readUnsignedByte(ByteBuffer buffer)
+ {
+ return buffer.getUnsigned();
+ }
+
+ protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte)
+ {
+ EncodingUtils.writeUnsignedByte(buffer, unsignedByte);
+ }
+
+ protected long readTimestamp(ByteBuffer buffer)
+ {
+ return EncodingUtils.readTimestamp(buffer);
+ }
+
+ protected void writeTimestamp(ByteBuffer buffer, long t)
+ {
+ EncodingUtils.writeTimestamp(buffer, t);
+ }
+
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
index 2fd4f70138..fd5195eb6b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_0_9/MethodConverter_0_9.java
@@ -1,172 +1,172 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.amqp_0_9;
-
-import org.apache.mina.common.ByteBuffer;
-
-import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.amqp_0_9.*;
-import org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl;
-
-public class MethodConverter_0_9 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
-{
- private int _basicPublishClassId;
- private int _basicPublishMethodId;
-
- public MethodConverter_0_9()
- {
- super((byte)0,(byte)9);
-
-
- }
-
- public AMQBody convertToBody(ContentChunk contentChunk)
- {
- if(contentChunk instanceof ContentChunk_0_9)
- {
- return ((ContentChunk_0_9)contentChunk).toBody();
- }
- else
- {
- return new ContentBody(contentChunk.getData());
- }
- }
-
- public ContentChunk convertToContentChunk(AMQBody body)
- {
- final ContentBody contentBodyChunk = (ContentBody) body;
-
- return new ContentChunk_0_9(contentBodyChunk);
-
- }
-
- public void configure()
- {
-
- _basicPublishClassId = org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl.CLASS_ID;
- _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID;
-
- }
-
- public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
- {
- final BasicPublishBody publishBody = ((BasicPublishBody) methodBody);
-
- final AMQShortString exchange = publishBody.getExchange();
- final AMQShortString routingKey = publishBody.getRoutingKey();
-
- return new MethodConverter_0_9.MessagePublishInfoImpl(exchange,
- publishBody.getImmediate(),
- publishBody.getMandatory(),
- routingKey);
-
- }
-
- public AMQMethodBody convertToBody(MessagePublishInfo info)
- {
-
- return new BasicPublishBodyImpl(0,
- info.getExchange(),
- info.getRoutingKey(),
- info.isMandatory(),
- info.isImmediate()) ;
-
- }
-
- private static class MessagePublishInfoImpl implements MessagePublishInfo
- {
- private AMQShortString _exchange;
- private final boolean _immediate;
- private final boolean _mandatory;
- private final AMQShortString _routingKey;
-
- public MessagePublishInfoImpl(final AMQShortString exchange,
- final boolean immediate,
- final boolean mandatory,
- final AMQShortString routingKey)
- {
- _exchange = exchange;
- _immediate = immediate;
- _mandatory = mandatory;
- _routingKey = routingKey;
- }
-
- public AMQShortString getExchange()
- {
- return _exchange;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- _exchange = exchange;
- }
-
- public boolean isImmediate()
- {
- return _immediate;
- }
-
- public boolean isMandatory()
- {
- return _mandatory;
- }
-
- public AMQShortString getRoutingKey()
- {
- return _routingKey;
- }
- }
-
- private static class ContentChunk_0_9 implements ContentChunk
- {
- private final ContentBody _contentBodyChunk;
-
- public ContentChunk_0_9(final ContentBody contentBodyChunk)
- {
- _contentBodyChunk = contentBodyChunk;
- }
-
- public int getSize()
- {
- return _contentBodyChunk.getSize();
- }
-
- public ByteBuffer getData()
- {
- return _contentBodyChunk.payload;
- }
-
- public void reduceToFit()
- {
- _contentBodyChunk.reduceBufferToFit();
- }
-
- public AMQBody toBody()
- {
- return _contentBodyChunk;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.amqp_0_9;
+
+import org.apache.mina.common.ByteBuffer;
+
+import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.framing.amqp_0_9.*;
+import org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl;
+
+public class MethodConverter_0_9 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
+{
+ private int _basicPublishClassId;
+ private int _basicPublishMethodId;
+
+ public MethodConverter_0_9()
+ {
+ super((byte)0,(byte)9);
+
+
+ }
+
+ public AMQBody convertToBody(ContentChunk contentChunk)
+ {
+ if(contentChunk instanceof ContentChunk_0_9)
+ {
+ return ((ContentChunk_0_9)contentChunk).toBody();
+ }
+ else
+ {
+ return new ContentBody(contentChunk.getData());
+ }
+ }
+
+ public ContentChunk convertToContentChunk(AMQBody body)
+ {
+ final ContentBody contentBodyChunk = (ContentBody) body;
+
+ return new ContentChunk_0_9(contentBodyChunk);
+
+ }
+
+ public void configure()
+ {
+
+ _basicPublishClassId = org.apache.qpid.framing.amqp_0_9.BasicPublishBodyImpl.CLASS_ID;
+ _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID;
+
+ }
+
+ public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
+ {
+ final BasicPublishBody publishBody = ((BasicPublishBody) methodBody);
+
+ final AMQShortString exchange = publishBody.getExchange();
+ final AMQShortString routingKey = publishBody.getRoutingKey();
+
+ return new MethodConverter_0_9.MessagePublishInfoImpl(exchange,
+ publishBody.getImmediate(),
+ publishBody.getMandatory(),
+ routingKey);
+
+ }
+
+ public AMQMethodBody convertToBody(MessagePublishInfo info)
+ {
+
+ return new BasicPublishBodyImpl(0,
+ info.getExchange(),
+ info.getRoutingKey(),
+ info.isMandatory(),
+ info.isImmediate()) ;
+
+ }
+
+ private static class MessagePublishInfoImpl implements MessagePublishInfo
+ {
+ private AMQShortString _exchange;
+ private final boolean _immediate;
+ private final boolean _mandatory;
+ private final AMQShortString _routingKey;
+
+ public MessagePublishInfoImpl(final AMQShortString exchange,
+ final boolean immediate,
+ final boolean mandatory,
+ final AMQShortString routingKey)
+ {
+ _exchange = exchange;
+ _immediate = immediate;
+ _mandatory = mandatory;
+ _routingKey = routingKey;
+ }
+
+ public AMQShortString getExchange()
+ {
+ return _exchange;
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+ _exchange = exchange;
+ }
+
+ public boolean isImmediate()
+ {
+ return _immediate;
+ }
+
+ public boolean isMandatory()
+ {
+ return _mandatory;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return _routingKey;
+ }
+ }
+
+ private static class ContentChunk_0_9 implements ContentChunk
+ {
+ private final ContentBody _contentBodyChunk;
+
+ public ContentChunk_0_9(final ContentBody contentBodyChunk)
+ {
+ _contentBodyChunk = contentBodyChunk;
+ }
+
+ public int getSize()
+ {
+ return _contentBodyChunk.getSize();
+ }
+
+ public ByteBuffer getData()
+ {
+ return _contentBodyChunk.payload;
+ }
+
+ public void reduceToFit()
+ {
+ _contentBodyChunk.reduceBufferToFit();
+ }
+
+ public AMQBody toBody()
+ {
+ return _contentBodyChunk;
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/AMQMethodBody_8_0.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/AMQMethodBody_8_0.java
index 2b7c9534a9..e9b4447140 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/AMQMethodBody_8_0.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/AMQMethodBody_8_0.java
@@ -1,209 +1,209 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.amqp_8_0;
-
-import org.apache.qpid.framing.EncodingUtils;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.Content;
-
-import org.apache.mina.common.ByteBuffer;
-
-public abstract class AMQMethodBody_8_0 extends org.apache.qpid.framing.AMQMethodBodyImpl
-{
-
- public byte getMajor()
- {
- return 8;
- }
-
- public byte getMinor()
- {
- return 0;
- }
-
- public int getSize()
- {
- return 2 + 2 + getBodySize();
- }
-
- public void writePayload(ByteBuffer buffer)
- {
- EncodingUtils.writeUnsignedShort(buffer, getClazz());
- EncodingUtils.writeUnsignedShort(buffer, getMethod());
- writeMethodPayload(buffer);
- }
-
-
- protected byte readByte(ByteBuffer buffer)
- {
- return buffer.get();
- }
-
- protected AMQShortString readAMQShortString(ByteBuffer buffer)
- {
- return EncodingUtils.readAMQShortString(buffer);
- }
-
- protected int getSizeOf(AMQShortString string)
- {
- return EncodingUtils.encodedShortStringLength(string);
- }
-
- protected void writeByte(ByteBuffer buffer, byte b)
- {
- buffer.put(b);
- }
-
- protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string)
- {
- EncodingUtils.writeShortStringBytes(buffer, string);
- }
-
- protected int readInt(ByteBuffer buffer)
- {
- return buffer.getInt();
- }
-
- protected void writeInt(ByteBuffer buffer, int i)
- {
- buffer.putInt(i);
- }
-
- protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
- {
- return EncodingUtils.readFieldTable(buffer);
- }
-
- protected int getSizeOf(FieldTable table)
- {
- return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeFieldTable(ByteBuffer buffer, FieldTable table)
- {
- EncodingUtils.writeFieldTableBytes(buffer, table);
- }
-
- protected long readLong(ByteBuffer buffer)
- {
- return buffer.getLong();
- }
-
- protected void writeLong(ByteBuffer buffer, long l)
- {
- buffer.putLong(l);
- }
-
- protected int getSizeOf(byte[] response)
- {
- return (response == null) ? 4 : response.length + 4;
- }
-
- protected void writeBytes(ByteBuffer buffer, byte[] data)
- {
- EncodingUtils.writeBytes(buffer,data);
- }
-
- protected byte[] readBytes(ByteBuffer buffer)
- {
- return EncodingUtils.readBytes(buffer);
- }
-
- protected short readShort(ByteBuffer buffer)
- {
- return EncodingUtils.readShort(buffer);
- }
-
- protected void writeShort(ByteBuffer buffer, short s)
- {
- EncodingUtils.writeShort(buffer, s);
- }
-
- protected Content readContent(ByteBuffer buffer)
- {
- return null; //To change body of created methods use File | Settings | File Templates.
- }
-
- protected int getSizeOf(Content body)
- {
- return 0; //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeContent(ByteBuffer buffer, Content body)
- {
- //To change body of created methods use File | Settings | File Templates.
- }
-
- protected byte readBitfield(ByteBuffer buffer)
- {
- return readByte(buffer); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected int readUnsignedShort(ByteBuffer buffer)
- {
- return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates.
- }
-
- protected void writeBitfield(ByteBuffer buffer, byte bitfield0)
- {
- buffer.put(bitfield0);
- }
-
- protected void writeUnsignedShort(ByteBuffer buffer, int s)
- {
- EncodingUtils.writeUnsignedShort(buffer, s);
- }
-
- protected long readUnsignedInteger(ByteBuffer buffer)
- {
- return buffer.getUnsignedInt();
- }
- protected void writeUnsignedInteger(ByteBuffer buffer, long i)
- {
- EncodingUtils.writeUnsignedInteger(buffer, i);
- }
-
-
- protected short readUnsignedByte(ByteBuffer buffer)
- {
- return buffer.getUnsigned();
- }
-
- protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte)
- {
- EncodingUtils.writeUnsignedByte(buffer, unsignedByte);
- }
-
- protected long readTimestamp(ByteBuffer buffer)
- {
- return EncodingUtils.readTimestamp(buffer);
- }
-
- protected void writeTimestamp(ByteBuffer buffer, long t)
- {
- EncodingUtils.writeTimestamp(buffer, t);
- }
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.amqp_8_0;
+
+import org.apache.qpid.framing.EncodingUtils;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.Content;
+
+import org.apache.mina.common.ByteBuffer;
+
+public abstract class AMQMethodBody_8_0 extends org.apache.qpid.framing.AMQMethodBodyImpl
+{
+
+ public byte getMajor()
+ {
+ return 8;
+ }
+
+ public byte getMinor()
+ {
+ return 0;
+ }
+
+ public int getSize()
+ {
+ return 2 + 2 + getBodySize();
+ }
+
+ public void writePayload(ByteBuffer buffer)
+ {
+ EncodingUtils.writeUnsignedShort(buffer, getClazz());
+ EncodingUtils.writeUnsignedShort(buffer, getMethod());
+ writeMethodPayload(buffer);
+ }
+
+
+ protected byte readByte(ByteBuffer buffer)
+ {
+ return buffer.get();
+ }
+
+ protected AMQShortString readAMQShortString(ByteBuffer buffer)
+ {
+ return EncodingUtils.readAMQShortString(buffer);
+ }
+
+ protected int getSizeOf(AMQShortString string)
+ {
+ return EncodingUtils.encodedShortStringLength(string);
+ }
+
+ protected void writeByte(ByteBuffer buffer, byte b)
+ {
+ buffer.put(b);
+ }
+
+ protected void writeAMQShortString(ByteBuffer buffer, AMQShortString string)
+ {
+ EncodingUtils.writeShortStringBytes(buffer, string);
+ }
+
+ protected int readInt(ByteBuffer buffer)
+ {
+ return buffer.getInt();
+ }
+
+ protected void writeInt(ByteBuffer buffer, int i)
+ {
+ buffer.putInt(i);
+ }
+
+ protected FieldTable readFieldTable(ByteBuffer buffer) throws AMQFrameDecodingException
+ {
+ return EncodingUtils.readFieldTable(buffer);
+ }
+
+ protected int getSizeOf(FieldTable table)
+ {
+ return EncodingUtils.encodedFieldTableLength(table); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeFieldTable(ByteBuffer buffer, FieldTable table)
+ {
+ EncodingUtils.writeFieldTableBytes(buffer, table);
+ }
+
+ protected long readLong(ByteBuffer buffer)
+ {
+ return buffer.getLong();
+ }
+
+ protected void writeLong(ByteBuffer buffer, long l)
+ {
+ buffer.putLong(l);
+ }
+
+ protected int getSizeOf(byte[] response)
+ {
+ return (response == null) ? 4 : response.length + 4;
+ }
+
+ protected void writeBytes(ByteBuffer buffer, byte[] data)
+ {
+ EncodingUtils.writeBytes(buffer,data);
+ }
+
+ protected byte[] readBytes(ByteBuffer buffer)
+ {
+ return EncodingUtils.readBytes(buffer);
+ }
+
+ protected short readShort(ByteBuffer buffer)
+ {
+ return EncodingUtils.readShort(buffer);
+ }
+
+ protected void writeShort(ByteBuffer buffer, short s)
+ {
+ EncodingUtils.writeShort(buffer, s);
+ }
+
+ protected Content readContent(ByteBuffer buffer)
+ {
+ return null; //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected int getSizeOf(Content body)
+ {
+ return 0; //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeContent(ByteBuffer buffer, Content body)
+ {
+ //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected byte readBitfield(ByteBuffer buffer)
+ {
+ return readByte(buffer); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected int readUnsignedShort(ByteBuffer buffer)
+ {
+ return buffer.getUnsignedShort(); //To change body of created methods use File | Settings | File Templates.
+ }
+
+ protected void writeBitfield(ByteBuffer buffer, byte bitfield0)
+ {
+ buffer.put(bitfield0);
+ }
+
+ protected void writeUnsignedShort(ByteBuffer buffer, int s)
+ {
+ EncodingUtils.writeUnsignedShort(buffer, s);
+ }
+
+ protected long readUnsignedInteger(ByteBuffer buffer)
+ {
+ return buffer.getUnsignedInt();
+ }
+ protected void writeUnsignedInteger(ByteBuffer buffer, long i)
+ {
+ EncodingUtils.writeUnsignedInteger(buffer, i);
+ }
+
+
+ protected short readUnsignedByte(ByteBuffer buffer)
+ {
+ return buffer.getUnsigned();
+ }
+
+ protected void writeUnsignedByte(ByteBuffer buffer, short unsignedByte)
+ {
+ EncodingUtils.writeUnsignedByte(buffer, unsignedByte);
+ }
+
+ protected long readTimestamp(ByteBuffer buffer)
+ {
+ return EncodingUtils.readTimestamp(buffer);
+ }
+
+ protected void writeTimestamp(ByteBuffer buffer, long t)
+ {
+ EncodingUtils.writeTimestamp(buffer, t);
+ }
+
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
index b1be49a350..299c655698 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java
@@ -1,151 +1,151 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.framing.amqp_8_0;
-
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
-import org.apache.qpid.framing.abstraction.ContentChunk;
-import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
-import org.apache.qpid.framing.amqp_8_0.BasicPublishBodyImpl;
-import org.apache.qpid.framing.*;
-
-import org.apache.mina.common.ByteBuffer;
-
-public class MethodConverter_8_0 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
-{
- private int _basicPublishClassId;
- private int _basicPublishMethodId;
-
- public MethodConverter_8_0()
- {
- super((byte)8,(byte)0);
-
-
- }
-
- public AMQBody convertToBody(ContentChunk contentChunk)
- {
- return new ContentBody(contentChunk.getData());
- }
-
- public ContentChunk convertToContentChunk(AMQBody body)
- {
- final ContentBody contentBodyChunk = (ContentBody) body;
-
- return new ContentChunk()
- {
-
- public int getSize()
- {
- return contentBodyChunk.getSize();
- }
-
- public ByteBuffer getData()
- {
- return contentBodyChunk.payload;
- }
-
- public void reduceToFit()
- {
- contentBodyChunk.reduceBufferToFit();
- }
- };
-
- }
-
- public void configure()
- {
-
- _basicPublishClassId = BasicPublishBodyImpl.CLASS_ID;
- _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID;
-
- }
-
- public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
- {
- final BasicPublishBody publishBody = ((BasicPublishBody) methodBody);
-
- final AMQShortString exchange = publishBody.getExchange();
- final AMQShortString routingKey = publishBody.getRoutingKey();
-
- return new MessagePublishInfoImpl(exchange == null ? null : exchange.intern(),
- publishBody.getImmediate(),
- publishBody.getMandatory(),
- routingKey == null ? null : routingKey.intern());
-
- }
-
- public AMQMethodBody convertToBody(MessagePublishInfo info)
- {
-
- return new BasicPublishBodyImpl(0,
- info.getExchange(),
- info.getRoutingKey(),
- info.isMandatory(),
- info.isImmediate()) ;
-
- }
-
- private static class MessagePublishInfoImpl implements MessagePublishInfo
- {
- private AMQShortString _exchange;
- private final boolean _immediate;
- private final boolean _mandatory;
- private final AMQShortString _routingKey;
-
- public MessagePublishInfoImpl(final AMQShortString exchange,
- final boolean immediate,
- final boolean mandatory,
- final AMQShortString routingKey)
- {
- _exchange = exchange;
- _immediate = immediate;
- _mandatory = mandatory;
- _routingKey = routingKey;
- }
-
- public AMQShortString getExchange()
- {
- return _exchange;
- }
-
- public void setExchange(AMQShortString exchange)
- {
- _exchange = exchange;
- }
-
- public boolean isImmediate()
- {
- return _immediate;
- }
-
- public boolean isMandatory()
- {
- return _mandatory;
- }
-
- public AMQShortString getRoutingKey()
- {
- return _routingKey;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.framing.amqp_8_0;
+
+import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
+import org.apache.qpid.framing.abstraction.ContentChunk;
+import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.framing.abstraction.AbstractMethodConverter;
+import org.apache.qpid.framing.amqp_8_0.BasicPublishBodyImpl;
+import org.apache.qpid.framing.*;
+
+import org.apache.mina.common.ByteBuffer;
+
+public class MethodConverter_8_0 extends AbstractMethodConverter implements ProtocolVersionMethodConverter
+{
+ private int _basicPublishClassId;
+ private int _basicPublishMethodId;
+
+ public MethodConverter_8_0()
+ {
+ super((byte)8,(byte)0);
+
+
+ }
+
+ public AMQBody convertToBody(ContentChunk contentChunk)
+ {
+ return new ContentBody(contentChunk.getData());
+ }
+
+ public ContentChunk convertToContentChunk(AMQBody body)
+ {
+ final ContentBody contentBodyChunk = (ContentBody) body;
+
+ return new ContentChunk()
+ {
+
+ public int getSize()
+ {
+ return contentBodyChunk.getSize();
+ }
+
+ public ByteBuffer getData()
+ {
+ return contentBodyChunk.payload;
+ }
+
+ public void reduceToFit()
+ {
+ contentBodyChunk.reduceBufferToFit();
+ }
+ };
+
+ }
+
+ public void configure()
+ {
+
+ _basicPublishClassId = BasicPublishBodyImpl.CLASS_ID;
+ _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID;
+
+ }
+
+ public MessagePublishInfo convertToInfo(AMQMethodBody methodBody)
+ {
+ final BasicPublishBody publishBody = ((BasicPublishBody) methodBody);
+
+ final AMQShortString exchange = publishBody.getExchange();
+ final AMQShortString routingKey = publishBody.getRoutingKey();
+
+ return new MessagePublishInfoImpl(exchange == null ? null : exchange.intern(),
+ publishBody.getImmediate(),
+ publishBody.getMandatory(),
+ routingKey == null ? null : routingKey.intern());
+
+ }
+
+ public AMQMethodBody convertToBody(MessagePublishInfo info)
+ {
+
+ return new BasicPublishBodyImpl(0,
+ info.getExchange(),
+ info.getRoutingKey(),
+ info.isMandatory(),
+ info.isImmediate()) ;
+
+ }
+
+ private static class MessagePublishInfoImpl implements MessagePublishInfo
+ {
+ private AMQShortString _exchange;
+ private final boolean _immediate;
+ private final boolean _mandatory;
+ private final AMQShortString _routingKey;
+
+ public MessagePublishInfoImpl(final AMQShortString exchange,
+ final boolean immediate,
+ final boolean mandatory,
+ final AMQShortString routingKey)
+ {
+ _exchange = exchange;
+ _immediate = immediate;
+ _mandatory = mandatory;
+ _routingKey = routingKey;
+ }
+
+ public AMQShortString getExchange()
+ {
+ return _exchange;
+ }
+
+ public void setExchange(AMQShortString exchange)
+ {
+ _exchange = exchange;
+ }
+
+ public boolean isImmediate()
+ {
+ return _immediate;
+ }
+
+ public boolean isMandatory()
+ {
+ return _mandatory;
+ }
+
+ public AMQShortString getRoutingKey()
+ {
+ return _routingKey;
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
index b56a05f725..59003225b7 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
@@ -1,57 +1,57 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.protocol;
-
-import org.apache.qpid.framing.*;
-import org.apache.qpid.AMQException;
-
-/**
- * AMQVersionAwareProtocolSession is implemented by all AMQP session classes, that need to provide an awareness to
- * callers of the version of the AMQP protocol that they are able to work with.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Provide the method registry for a specific version of the AMQP.
- * </table>
- *
- * @todo Why is this a seperate interface to {@link ProtocolVersionAware}, could they be combined into a single
- * interface and one of them eliminated? Move getRegistry method to ProtocolVersionAware, make the sessions
- * implement AMQProtocolWriter directly and drop this interface.
- */
-public interface AMQVersionAwareProtocolSession extends AMQProtocolWriter, ProtocolVersionAware
-{
- /**
- * Gets the method registry for a specific version of the AMQP.
- *
- * @return The method registry for a specific version of the AMQP.
- */
-// public VersionSpecificRegistry getRegistry();
-
- MethodRegistry getMethodRegistry();
-
-
- public void methodFrameReceived(int channelId, AMQMethodBody body) throws AMQException;
- public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException;
- public void contentBodyReceived(int channelId, ContentBody body) throws AMQException;
- public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException;
-
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.protocol;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.AMQException;
+
+/**
+ * AMQVersionAwareProtocolSession is implemented by all AMQP session classes, that need to provide an awareness to
+ * callers of the version of the AMQP protocol that they are able to work with.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide the method registry for a specific version of the AMQP.
+ * </table>
+ *
+ * @todo Why is this a seperate interface to {@link ProtocolVersionAware}, could they be combined into a single
+ * interface and one of them eliminated? Move getRegistry method to ProtocolVersionAware, make the sessions
+ * implement AMQProtocolWriter directly and drop this interface.
+ */
+public interface AMQVersionAwareProtocolSession extends AMQProtocolWriter, ProtocolVersionAware
+{
+ /**
+ * Gets the method registry for a specific version of the AMQP.
+ *
+ * @return The method registry for a specific version of the AMQP.
+ */
+// public VersionSpecificRegistry getRegistry();
+
+ MethodRegistry getMethodRegistry();
+
+
+ public void methodFrameReceived(int channelId, AMQMethodBody body) throws AMQException;
+ public void contentHeaderReceived(int channelId, ContentHeaderBody body) throws AMQException;
+ public void contentBodyReceived(int channelId, ContentBody body) throws AMQException;
+ public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException;
+
+
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolVersionAware.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolVersionAware.java
index dea80cdcf4..56f950dd85 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolVersionAware.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolVersionAware.java
@@ -1,53 +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.protocol;
-
-import org.apache.qpid.framing.ProtocolVersion;
-
-/**
- * ProtocolVersionAware is implemented by all AMQP handling classes, that need to provide an awareness to callers of
- * the version of the AMQP protocol that they are able to handle.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Report the major and minor AMQP version handled.
- * </table>
- */
-public interface ProtocolVersionAware
-{
- /**
- * @deprecated
- * Reports the AMQP minor version, that the implementer can handle.
- *
- * @return The AMQP minor version.
- */
- public byte getProtocolMinorVersion();
-
- /**
- * @deprecated
- * Reports the AMQP major version, that the implementer can handle.
- *
- * @return The AMQP major version.
- */
- public byte getProtocolMajorVersion();
-
- public ProtocolVersion getProtocolVersion();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.protocol;
+
+import org.apache.qpid.framing.ProtocolVersion;
+
+/**
+ * ProtocolVersionAware is implemented by all AMQP handling classes, that need to provide an awareness to callers of
+ * the version of the AMQP protocol that they are able to handle.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Report the major and minor AMQP version handled.
+ * </table>
+ */
+public interface ProtocolVersionAware
+{
+ /**
+ * @deprecated
+ * Reports the AMQP minor version, that the implementer can handle.
+ *
+ * @return The AMQP minor version.
+ */
+ public byte getProtocolMinorVersion();
+
+ /**
+ * @deprecated
+ * Reports the AMQP major version, that the implementer can handle.
+ *
+ * @return The AMQP major version.
+ */
+ public byte getProtocolMajorVersion();
+
+ public ProtocolVersion getProtocolVersion();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java b/qpid/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
index dc73bce28f..baa68f87f9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/CommandLineParser.java
@@ -1,689 +1,689 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.*;
-
-/**
- * CommandLineParser provides a utility for specifying the format of a command line and parsing command lines to ensure
- * that they fit their specified format. A command line is made up of flags and options, both may be refered to as
- * options. A flag is an option that does not take an argument (specifying it means it has the value 'true' and not
- * specifying it means it has the value 'false'). Options must take arguments but they can be set up with defaults so
- * that they take a default value when not set. Options may be mandatory in wich case it is an error not to specify
- * them on the command line. Flags are never mandatory because they are implicitly set to false when not specified.
- *
- * <p/>Some example command lines are:
- *
- * <ul>
- * <li>This one has two options that expect arguments:
- * <pre>
- * cruisecontrol -configfile cruisecontrol.xml -port 9000
- * </pre>
- * <li>This has one no-arg flag and two 'free' arguments:
- * <pre>
- * zip -r project.zip project/*
- * </pre>
- * <li>This one concatenates multiple flags into a single block with only one '-':
- * <pre>
- * jar -tvf mytar.tar
- * </pre>
- *
- * <p/>The parsing rules are:
- *
- * <ol>
- * <li>Flags may be combined after a single '-' because they never take arguments. Normally such flags are single letter
- * flags but this is only a convention and not enforced. Flags of more than one letter are usually specified on their own.
- * <li>Options expecting arguments must always be on their own.
- * <li>The argument to an option may be seperated from it by whitespace or appended directly onto the option.
- * <li>The argument to an option may never begin with a '-' character.
- * <li>All other arguments not beginning with a '-' character are free arguments that do not belong to any option.
- * <li>The second or later of a set of duplicate or repeated flags are ignored.
- * <li>Options are matched up to the shortest matching option. This is because of the possibility of having no space
- * between an option and its argument. This rules out the possibility of using two options where one is an opening
- * substring of the other. For example, the options "foo" and "foobar" cannot be used on the same command line because
- * it is not possible to distinguish the argument "-foobar" from being the "foobar" option or the "foo" option with
- * the "bar" argument.
- * </ol>
- *
- * <p/>By default, unknown options are simply ignored if specified on the command line. This behaviour may be changed
- * so that the parser reports all unknowns as errors by using the {@link #setErrorsOnUnknowns} method.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept a command line specification.
- * <tr><td> Parse a command line into properties, validating it against its specification.
- * <tr><td> Report all errors between a command line and its specification.
- * <tr><td> Provide a formatted usage string for a command line.
- * <tr><td> Provide a formatted options in force string for a command line.
- * <tr><td> Allow errors on unknowns behaviour to be turned on or off.
- * </table>
- */
-public class CommandLineParser
-{
- /** Holds a mapping from command line option names to detailed information about those options. */
- private Map<String, CommandLineOption> optionMap = new HashMap<String, CommandLineOption>();
-
- /** Holds a list of parsing errors. */
- private List<String> parsingErrors = new ArrayList<String>();
-
- /** Holds the regular expression matcher to match command line options with. */
- private Matcher optionMatcher = null;
-
- /** Holds the parsed command line properties after parsing. */
- private Properties parsedProperties = null;
-
- /** Flag used to indicate that errors should be created for unknown options. False by default. */
- private boolean errorsOnUnknowns = false;
-
- /**
- * Creates a command line options parser from a command line specification. This is passed to this constructor
- * as an array of arrays of strings. Each array of strings specifies the command line for a single option. A static
- * array may therefore easily be used to configure the command line parser in a single method call with an easily
- * readable format.
- *
- * <p/>Each array of strings must be 2, 3, 4 or 5 elements long. If any of the last three elements are missing they
- * are assumed to be null. The elements specify the following parameters:
- * <ol>
- * <li>The name of the option without the leading '-'. For example, "file". To specify the format of the 'free'
- * arguments use the option names "1", "2", ... and so on.
- * <li>The option comment. A line of text describing the usage of the option. For example, "The file to be processed."
- * <li>The options argument. This is a very short description of the argument to the option, often a single word
- * or a reminder as to the arguments format. When this element is null the option is a flag and does not
- * accept any arguments. For example, "filename" or "(unix | windows)" or null. The actual text specified
- * is only used to print in the usage message to remind the user of the usage of the option.
- * <li>The mandatory flag. When set to "true" an option must always be specified. Any other value, including null,
- * means that the option is mandatory. Flags are always mandatory (see class javadoc for explanation of why) so
- * this is ignored for flags.
- * <li>A regular expression describing the format that the argument must take. Ignored if null.
- * </ol>
- * <p/>An example call to this constructor is:
- *
- * <pre>
- * CommandLineParser commandLine = new CommandLineParser(
- * new String[][] {{"file", "The file to be processed. ", "filename", "true"},
- * {"dir", "Directory to store results in. Current dir used if not set.", "out dir"},
- * {"os", "Operating system EOL format to use.", "(windows | unix)", null, "windows\|unix"},
- * {"v", "Verbose mode. Prints information about the processing as it goes."},
- * {"1", "The processing command to run.", "command", "true", "add\|remove\|list"}});
- * </pre>
- *
- * @param config The configuration as an array of arrays of strings.
- */
- public CommandLineParser(String[][] config)
- {
- // Loop through all the command line option specifications creating details for each in the options map.
- for (int i = 0; i < config.length; i++)
- {
- String[] nextOptionSpec = config[i];
-
- addOption(nextOptionSpec[0], nextOptionSpec[1], (nextOptionSpec.length > 2) ? nextOptionSpec[2] : null,
- (nextOptionSpec.length > 3) ? ("true".equals(nextOptionSpec[3]) ? true : false) : false,
- (nextOptionSpec.length > 4) ? nextOptionSpec[4] : null);
- }
- }
-
- /**
- * Lists all the parsing errors from the most recent parsing in a string.
- *
- * @return All the parsing errors from the most recent parsing.
- */
- public String getErrors()
- {
- // Return the empty string if there are no errors.
- if (parsingErrors.isEmpty())
- {
- return "";
- }
-
- // Concatenate all the parsing errors together.
- String result = "";
-
- for (String s : parsingErrors)
- {
- result += s;
- }
-
- return result;
- }
-
- /**
- * Lists the properties set from the most recent parsing or an empty string if no parsing has been done yet.
- *
- * @return The properties set from the most recent parsing or an empty string if no parsing has been done yet.
- */
- public String getOptionsInForce()
- {
- // Check if there are no properties to report and return and empty string if so.
- if (parsedProperties == null)
- {
- return "";
- }
-
- // List all the properties.
- String result = "Options in force:\n";
-
- for (Map.Entry<Object, Object> property : parsedProperties.entrySet())
- {
- result += property.getKey() + " = " + property.getValue() + "\n";
- }
-
- return result;
- }
-
- /**
- * Generates a usage string consisting of the name of each option and each options argument description and
- * comment.
- *
- * @return A usage string for all the options.
- */
- public String getUsage()
- {
- String result = "Options:\n";
-
- // Print usage on each of the command line options.
- for (CommandLineOption optionInfo : optionMap.values())
- {
- result +=
- optionInfo.option + " " + ((optionInfo.argument != null) ? (optionInfo.argument + " ") : "")
- + optionInfo.comment + "\n";
- }
-
- return result;
- }
-
- /**
- * Control the behaviour of the errors on unkowns reporting. When turned on this reports all unkowns options
- * as errors. When turned off, all unknowns are simply ignored.
- *
- * @param errors The setting of the errors on unkown flag. True to turn it on.
- */
- public void setErrorsOnUnknowns(boolean errors)
- {
- errorsOnUnknowns = errors;
- }
-
- /**
- * Parses a set of command line arguments into a set of properties, keyed by the argument flag. The free arguments
- * are keyed by integers as strings starting at "1" and then "2", ... and so on.
- *
- * <p/>See the class level comment for a description of the parsing rules.
- *
- * @param args The command line arguments.
- *
- * @return The arguments as a set of properties.
- *
- * @throws IllegalArgumentException If the command line cannot be parsed against its specification. If this exception
- * is thrown a call to {@link #getErrors} will provide a diagnostic of the command
- * line errors.
- */
- public Properties parseCommandLine(String[] args) throws IllegalArgumentException
- {
- Properties options = new Properties();
-
- // Used to keep count of the current 'free' argument.
- int free = 1;
-
- // Used to indicate that the most recently parsed option is expecting arguments.
- boolean expectingArgs = false;
-
- // The option that is expecting arguments from the next element of the command line.
- String optionExpectingArgs = null;
-
- // Used to indicate that the most recently parsed option is a duplicate and should be ignored.
- boolean ignore = false;
-
- // Create the regular expression matcher for the command line options.
- String regexp = "^(";
- int optionsAdded = 0;
-
- for (Iterator<String> i = optionMap.keySet().iterator(); i.hasNext();)
- {
- String nextOption = i.next();
-
- // Check that the option is not a free argument definition.
- boolean notFree = false;
-
- try
- {
- Integer.parseInt(nextOption);
- }
- catch (NumberFormatException e)
- {
- notFree = true;
- }
-
- // Add the option to the regular expression matcher if it is not a free argument definition.
- if (notFree)
- {
- regexp += nextOption + (i.hasNext() ? "|" : "");
- optionsAdded++;
- }
- }
-
- // There has to be more that one option in the regular expression or else the compiler complains that the close
- // cannot be nullable if the '?' token is used to make the matched option string optional.
- regexp += ")" + ((optionsAdded > 0) ? "?" : "") + "(.*)";
- Pattern pattern = Pattern.compile(regexp);
-
- // Loop through all the command line arguments.
- for (int i = 0; i < args.length; i++)
- {
- // Check if the next command line argument begins with a '-' character and is therefore the start of
- // an option.
- if (args[i].startsWith("-"))
- {
- // Extract the value of the option without the leading '-'.
- String arg = args[i].substring(1);
-
- // Match up to the longest matching option.
- optionMatcher = pattern.matcher(arg);
- optionMatcher.matches();
-
- String matchedOption = optionMatcher.group(1);
-
- // Match any argument directly appended onto the longest matching option.
- String matchedArg = optionMatcher.group(2);
-
- // Check that a known option was matched.
- if ((matchedOption != null) && !"".equals(matchedOption))
- {
- // Get the command line option information for the matched option.
- CommandLineOption optionInfo = optionMap.get(matchedOption);
-
- // Check if this option is expecting arguments.
- if (optionInfo.expectsArgs)
- {
- // The option is expecting arguments so swallow the next command line argument as an
- // argument to this option.
- expectingArgs = true;
- optionExpectingArgs = matchedOption;
-
- // In the mean time set this options argument to the empty string in case no argument is ever
- // supplied.
- // options.put(matchedOption, "");
- }
-
- // Check if the option was matched on its own and is a flag in which case set that flag.
- if ("".equals(matchedArg) && !optionInfo.expectsArgs)
- {
- options.put(matchedOption, "true");
- }
- // The option was matched as a substring with its argument appended to it or is a flag that is
- // condensed together with other flags.
- else if (!"".equals(matchedArg))
- {
- // Check if the option is a flag and therefore is allowed to be condensed together
- // with other flags.
- if (!optionInfo.expectsArgs)
- {
- // Set the first matched flag.
- options.put(matchedOption, "true");
-
- // Repeat the longest matching process on the remainder but ensure that the remainder
- // consists only of flags as only flags may be condensed together in this fashion.
- do
- {
- // Match the remainder against the options.
- optionMatcher = pattern.matcher(matchedArg);
- optionMatcher.matches();
-
- matchedOption = optionMatcher.group(1);
- matchedArg = optionMatcher.group(2);
-
- // Check that an option was matched.
- if (matchedOption != null)
- {
- // Get the command line option information for the next matched option.
- optionInfo = optionMap.get(matchedOption);
-
- // Ensure that the next option is a flag or raise an error if not.
- if (optionInfo.expectsArgs == true)
- {
- parsingErrors.add("Option " + matchedOption + " cannot be combined with flags.\n");
- }
-
- options.put(matchedOption, "true");
- }
- // The remainder could not be matched against a flag it is either an unknown flag
- // or an illegal argument to a flag.
- else
- {
- parsingErrors.add("Illegal argument to a flag in the option " + arg + "\n");
-
- break;
- }
- }
- // Continue until the remainder of the argument has all been matched with flags.
- while (!"".equals(matchedArg));
- }
- // The option is expecting an argument, so store the unmatched portion against it
- // as its argument.
- else
- {
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, matchedArg);
-
- // Store the argument against its option (regardless of its format).
- options.put(matchedOption, matchedArg);
-
- // The argument to this flag has already been supplied to it. Do not swallow the
- // next command line argument as an argument to this flag.
- expectingArgs = false;
- }
- }
- }
- else // No matching option was found.
- {
- // Add this to the list of parsing errors if errors on unkowns is being used.
- if (errorsOnUnknowns)
- {
- parsingErrors.add("Option " + matchedOption + " is not a recognized option.\n");
- }
- }
- }
- // The command line argument did not being with a '-' so it is an argument to the previous flag or it
- // is a free argument.
- else
- {
- // Check if a previous flag is expecting to swallow this next argument as its argument.
- if (expectingArgs)
- {
- // Get the option info for the option waiting for arguments.
- CommandLineOption optionInfo = optionMap.get(optionExpectingArgs);
-
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, args[i]);
-
- // Store the argument against its option (regardless of its format).
- options.put(optionExpectingArgs, args[i]);
-
- // Clear the expecting args flag now that the argument has been swallowed.
- expectingArgs = false;
- optionExpectingArgs = null;
- }
- // This command line option is not an argument to any option. Add it to the set of 'free' options.
- else
- {
- // Get the option info for the free option, if there is any.
- CommandLineOption optionInfo = optionMap.get(Integer.toString(free));
-
- if (optionInfo != null)
- {
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, args[i]);
- }
-
- // Add to the list of free options.
- options.put(Integer.toString(free), args[i]);
-
- // Move on to the next free argument.
- free++;
- }
- }
- }
-
- // Scan through all the specified options to check that all mandatory options have been set and that all flags
- // that were not set are set to false in the set of properties.
- for (CommandLineOption optionInfo : optionMap.values())
- {
- // Check if this is a flag.
- if (!optionInfo.expectsArgs)
- {
- // Check if the flag is not set in the properties and set it to false if so.
- if (!options.containsKey(optionInfo.option))
- {
- options.put(optionInfo.option, "false");
- }
- }
- // Check if this is a mandatory option and was not set.
- else if (optionInfo.mandatory && !options.containsKey(optionInfo.option))
- {
- // Create an error for the missing option.
- parsingErrors.add("Option " + optionInfo.option + " is mandatory but not was not specified.\n");
- }
- }
-
- // Check if there were any errors.
- if (!parsingErrors.isEmpty())
- {
- // Throw an illegal argument exception to signify that there were parsing errors.
- throw new IllegalArgumentException();
- }
-
- // Convert any name/value pairs in the free arguments into properties in the parsed options.
- options = takeFreeArgsAsProperties(options, 1);
-
- parsedProperties = options;
-
- return options;
- }
-
- /**
- * If a command line has been parsed, calling this method sets all of its parsed options into the specified properties.
- */
- public void addCommandLineToProperties(Properties properties)
- {
- if (parsedProperties != null)
- {
- for (Object propKey : parsedProperties.keySet())
- {
- String name = (String) propKey;
- String value = parsedProperties.getProperty(name);
-
- properties.setProperty(name, value);
- }
- }
- }
-
- /**
- * Resets this command line parser after it has been used to parse a command line. This method will only need
- * to be called to use this parser a second time which is not likely seeing as a command line is usually only
- * specified once. However, it is exposed as a public method for the rare case where this may be done.
- *
- * <p/>Cleans the internal state of this parser, removing all stored errors and information about the options in
- * force.
- */
- public void reset()
- {
- parsingErrors = new ArrayList<String>();
- parsedProperties = null;
- }
-
- /**
- * Adds the option to list of available command line options.
- *
- * @param option The option to add as an available command line option.
- * @param comment A comment for the option.
- * @param argument The text that appears after the option in the usage string.
- * @param mandatory When true, indicates that this option is mandatory.
- * @param formatRegexp The format that the argument must take, defined as a regular expression.
- */
- protected void addOption(String option, String comment, String argument, boolean mandatory, String formatRegexp)
- {
- // Check if usage text has been set in which case this option is expecting arguments.
- boolean expectsArgs = ((argument == null) || argument.equals("")) ? false : true;
-
- // Add the option to the map of command line options.
- CommandLineOption opt = new CommandLineOption(option, expectsArgs, comment, argument, mandatory, formatRegexp);
- optionMap.put(option, opt);
- }
-
- /**
- * Converts the free arguments into property declarations. After parsing the command line the free arguments
- * are numbered from 1, such that the parsed properties contain values for the keys "1", "2", ... This method
- * converts any free arguments declared using the 'name=value' syntax into properties with key 'name', value
- * 'value'.
- *
- * <p/>For example the comand line:
- * <pre>
- * ... debug=true
- * </pre>
- *
- * <p/>After parsing has properties:
- * <pre>[[1, debug=true]]</pre>
- *
- * <p/>After applying this method the properties are:
- * <pre>[[1, debug=true], [debug, true]]</pre>
- *
- * @param properties The parsed command line properties.
- * @param from The free argument index to convert to properties from.
- *
- * @return The parsed command line properties, with free argument name value pairs too.
- */
- private Properties takeFreeArgsAsProperties(Properties properties, int from)
- {
- for (int i = from; true; i++)
- {
- String nextFreeArg = properties.getProperty(Integer.toString(i));
-
- // Terminate the loop once all free arguments have been consumed.
- if (nextFreeArg == null)
- {
- break;
- }
-
- // Split it on the =, strip any whitespace and set it as a system property.
- String[] nameValuePair = nextFreeArg.split("=");
-
- if (nameValuePair.length == 2)
- {
- properties.setProperty(nameValuePair[0], nameValuePair[1]);
- }
- }
-
- return properties;
- }
-
- /**
- * Checks the format of an argument to an option against its specified regular expression format if one has
- * been set. Any errors are added to the list of parsing errors.
- *
- * @param optionInfo The command line option information for the option which is havings its argument checked.
- * @param matchedArg The string argument to the option.
- */
- private void checkArgumentFormat(CommandLineOption optionInfo, String matchedArg)
- {
- // Check if this option enforces a format for its argument.
- if (optionInfo.argumentFormatRegexp != null)
- {
- Pattern pattern = Pattern.compile(optionInfo.argumentFormatRegexp);
- Matcher argumentMatcher = pattern.matcher(matchedArg);
-
- // Check if the argument does not meet its required format.
- if (!argumentMatcher.matches())
- {
- // Create an error for this badly formed argument.
- parsingErrors.add("The argument to option " + optionInfo.option + " does not meet its required format.\n");
- }
- }
- }
-
- /**
- * Extracts all name=value pairs from the command line, sets them all as system properties and also returns
- * a map of properties containing them.
- *
- * @param args The command line.
- * @param commandLine The command line parser.
- * @param properties The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
- *
- * @return A set of properties containing all name=value pairs from the command line.
- */
- public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
- {
- // Capture the command line arguments or display errors and correct usage and then exit.
- Properties options = null;
-
- try
- {
- options = commandLine.parseCommandLine(args);
-
- // Add all the trailing command line options (name=value pairs) to system properties. They may be picked up
- // from there.
- commandLine.addCommandLineToProperties(properties);
- }
- catch (IllegalArgumentException e)
- {
- System.out.println(commandLine.getErrors());
- System.out.println(commandLine.getUsage());
- System.exit(1);
- }
-
- return options;
- }
-
- /**
- * Holds information about a command line options. This includes what its name is, whether or not it is a flag,
- * whether or not it is mandatory, what its user comment is, what its argument reminder text is and what its
- * regular expression format is.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Hold details of a command line option.
- * </table>
- */
- protected class CommandLineOption
- {
- /** Holds the text for the flag to match this argument with. */
- public String option = null;
-
- /** Holds a string describing how to use this command line argument. */
- public String argument = null;
-
- /** Flag that determines whether or not this command line argument can take arguments. */
- public boolean expectsArgs = false;
-
- /** Holds a short comment describing what this command line argument is for. */
- public String comment = null;
-
- /** Flag that determines whether or not this is an mandatory command line argument. */
- public boolean mandatory = false;
-
- /** A regular expression describing what format the argument to this option muist have. */
- public String argumentFormatRegexp = null;
-
- /**
- * Create a command line option object that holds specific information about a command line option.
- *
- * @param option The text that matches the option.
- * @param expectsArgs Whether or not the option expects arguments. It is a flag if this is false.
- * @param comment A comment explaining how to use this option.
- * @param argument A short reminder of the format of the argument to this option/
- * @param mandatory Set to true if this option is mandatory.
- * @param formatRegexp The regular expression that the argument to this option must meet to be valid.
- */
- public CommandLineOption(String option, boolean expectsArgs, String comment, String argument, boolean mandatory,
- String formatRegexp)
- {
- this.option = option;
- this.expectsArgs = expectsArgs;
- this.comment = comment;
- this.argument = argument;
- this.mandatory = mandatory;
- this.argumentFormatRegexp = formatRegexp;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.*;
+
+/**
+ * CommandLineParser provides a utility for specifying the format of a command line and parsing command lines to ensure
+ * that they fit their specified format. A command line is made up of flags and options, both may be refered to as
+ * options. A flag is an option that does not take an argument (specifying it means it has the value 'true' and not
+ * specifying it means it has the value 'false'). Options must take arguments but they can be set up with defaults so
+ * that they take a default value when not set. Options may be mandatory in wich case it is an error not to specify
+ * them on the command line. Flags are never mandatory because they are implicitly set to false when not specified.
+ *
+ * <p/>Some example command lines are:
+ *
+ * <ul>
+ * <li>This one has two options that expect arguments:
+ * <pre>
+ * cruisecontrol -configfile cruisecontrol.xml -port 9000
+ * </pre>
+ * <li>This has one no-arg flag and two 'free' arguments:
+ * <pre>
+ * zip -r project.zip project/*
+ * </pre>
+ * <li>This one concatenates multiple flags into a single block with only one '-':
+ * <pre>
+ * jar -tvf mytar.tar
+ * </pre>
+ *
+ * <p/>The parsing rules are:
+ *
+ * <ol>
+ * <li>Flags may be combined after a single '-' because they never take arguments. Normally such flags are single letter
+ * flags but this is only a convention and not enforced. Flags of more than one letter are usually specified on their own.
+ * <li>Options expecting arguments must always be on their own.
+ * <li>The argument to an option may be seperated from it by whitespace or appended directly onto the option.
+ * <li>The argument to an option may never begin with a '-' character.
+ * <li>All other arguments not beginning with a '-' character are free arguments that do not belong to any option.
+ * <li>The second or later of a set of duplicate or repeated flags are ignored.
+ * <li>Options are matched up to the shortest matching option. This is because of the possibility of having no space
+ * between an option and its argument. This rules out the possibility of using two options where one is an opening
+ * substring of the other. For example, the options "foo" and "foobar" cannot be used on the same command line because
+ * it is not possible to distinguish the argument "-foobar" from being the "foobar" option or the "foo" option with
+ * the "bar" argument.
+ * </ol>
+ *
+ * <p/>By default, unknown options are simply ignored if specified on the command line. This behaviour may be changed
+ * so that the parser reports all unknowns as errors by using the {@link #setErrorsOnUnknowns} method.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept a command line specification.
+ * <tr><td> Parse a command line into properties, validating it against its specification.
+ * <tr><td> Report all errors between a command line and its specification.
+ * <tr><td> Provide a formatted usage string for a command line.
+ * <tr><td> Provide a formatted options in force string for a command line.
+ * <tr><td> Allow errors on unknowns behaviour to be turned on or off.
+ * </table>
+ */
+public class CommandLineParser
+{
+ /** Holds a mapping from command line option names to detailed information about those options. */
+ private Map<String, CommandLineOption> optionMap = new HashMap<String, CommandLineOption>();
+
+ /** Holds a list of parsing errors. */
+ private List<String> parsingErrors = new ArrayList<String>();
+
+ /** Holds the regular expression matcher to match command line options with. */
+ private Matcher optionMatcher = null;
+
+ /** Holds the parsed command line properties after parsing. */
+ private Properties parsedProperties = null;
+
+ /** Flag used to indicate that errors should be created for unknown options. False by default. */
+ private boolean errorsOnUnknowns = false;
+
+ /**
+ * Creates a command line options parser from a command line specification. This is passed to this constructor
+ * as an array of arrays of strings. Each array of strings specifies the command line for a single option. A static
+ * array may therefore easily be used to configure the command line parser in a single method call with an easily
+ * readable format.
+ *
+ * <p/>Each array of strings must be 2, 3, 4 or 5 elements long. If any of the last three elements are missing they
+ * are assumed to be null. The elements specify the following parameters:
+ * <ol>
+ * <li>The name of the option without the leading '-'. For example, "file". To specify the format of the 'free'
+ * arguments use the option names "1", "2", ... and so on.
+ * <li>The option comment. A line of text describing the usage of the option. For example, "The file to be processed."
+ * <li>The options argument. This is a very short description of the argument to the option, often a single word
+ * or a reminder as to the arguments format. When this element is null the option is a flag and does not
+ * accept any arguments. For example, "filename" or "(unix | windows)" or null. The actual text specified
+ * is only used to print in the usage message to remind the user of the usage of the option.
+ * <li>The mandatory flag. When set to "true" an option must always be specified. Any other value, including null,
+ * means that the option is mandatory. Flags are always mandatory (see class javadoc for explanation of why) so
+ * this is ignored for flags.
+ * <li>A regular expression describing the format that the argument must take. Ignored if null.
+ * </ol>
+ * <p/>An example call to this constructor is:
+ *
+ * <pre>
+ * CommandLineParser commandLine = new CommandLineParser(
+ * new String[][] {{"file", "The file to be processed. ", "filename", "true"},
+ * {"dir", "Directory to store results in. Current dir used if not set.", "out dir"},
+ * {"os", "Operating system EOL format to use.", "(windows | unix)", null, "windows\|unix"},
+ * {"v", "Verbose mode. Prints information about the processing as it goes."},
+ * {"1", "The processing command to run.", "command", "true", "add\|remove\|list"}});
+ * </pre>
+ *
+ * @param config The configuration as an array of arrays of strings.
+ */
+ public CommandLineParser(String[][] config)
+ {
+ // Loop through all the command line option specifications creating details for each in the options map.
+ for (int i = 0; i < config.length; i++)
+ {
+ String[] nextOptionSpec = config[i];
+
+ addOption(nextOptionSpec[0], nextOptionSpec[1], (nextOptionSpec.length > 2) ? nextOptionSpec[2] : null,
+ (nextOptionSpec.length > 3) ? ("true".equals(nextOptionSpec[3]) ? true : false) : false,
+ (nextOptionSpec.length > 4) ? nextOptionSpec[4] : null);
+ }
+ }
+
+ /**
+ * Lists all the parsing errors from the most recent parsing in a string.
+ *
+ * @return All the parsing errors from the most recent parsing.
+ */
+ public String getErrors()
+ {
+ // Return the empty string if there are no errors.
+ if (parsingErrors.isEmpty())
+ {
+ return "";
+ }
+
+ // Concatenate all the parsing errors together.
+ String result = "";
+
+ for (String s : parsingErrors)
+ {
+ result += s;
+ }
+
+ return result;
+ }
+
+ /**
+ * Lists the properties set from the most recent parsing or an empty string if no parsing has been done yet.
+ *
+ * @return The properties set from the most recent parsing or an empty string if no parsing has been done yet.
+ */
+ public String getOptionsInForce()
+ {
+ // Check if there are no properties to report and return and empty string if so.
+ if (parsedProperties == null)
+ {
+ return "";
+ }
+
+ // List all the properties.
+ String result = "Options in force:\n";
+
+ for (Map.Entry<Object, Object> property : parsedProperties.entrySet())
+ {
+ result += property.getKey() + " = " + property.getValue() + "\n";
+ }
+
+ return result;
+ }
+
+ /**
+ * Generates a usage string consisting of the name of each option and each options argument description and
+ * comment.
+ *
+ * @return A usage string for all the options.
+ */
+ public String getUsage()
+ {
+ String result = "Options:\n";
+
+ // Print usage on each of the command line options.
+ for (CommandLineOption optionInfo : optionMap.values())
+ {
+ result +=
+ optionInfo.option + " " + ((optionInfo.argument != null) ? (optionInfo.argument + " ") : "")
+ + optionInfo.comment + "\n";
+ }
+
+ return result;
+ }
+
+ /**
+ * Control the behaviour of the errors on unkowns reporting. When turned on this reports all unkowns options
+ * as errors. When turned off, all unknowns are simply ignored.
+ *
+ * @param errors The setting of the errors on unkown flag. True to turn it on.
+ */
+ public void setErrorsOnUnknowns(boolean errors)
+ {
+ errorsOnUnknowns = errors;
+ }
+
+ /**
+ * Parses a set of command line arguments into a set of properties, keyed by the argument flag. The free arguments
+ * are keyed by integers as strings starting at "1" and then "2", ... and so on.
+ *
+ * <p/>See the class level comment for a description of the parsing rules.
+ *
+ * @param args The command line arguments.
+ *
+ * @return The arguments as a set of properties.
+ *
+ * @throws IllegalArgumentException If the command line cannot be parsed against its specification. If this exception
+ * is thrown a call to {@link #getErrors} will provide a diagnostic of the command
+ * line errors.
+ */
+ public Properties parseCommandLine(String[] args) throws IllegalArgumentException
+ {
+ Properties options = new Properties();
+
+ // Used to keep count of the current 'free' argument.
+ int free = 1;
+
+ // Used to indicate that the most recently parsed option is expecting arguments.
+ boolean expectingArgs = false;
+
+ // The option that is expecting arguments from the next element of the command line.
+ String optionExpectingArgs = null;
+
+ // Used to indicate that the most recently parsed option is a duplicate and should be ignored.
+ boolean ignore = false;
+
+ // Create the regular expression matcher for the command line options.
+ String regexp = "^(";
+ int optionsAdded = 0;
+
+ for (Iterator<String> i = optionMap.keySet().iterator(); i.hasNext();)
+ {
+ String nextOption = i.next();
+
+ // Check that the option is not a free argument definition.
+ boolean notFree = false;
+
+ try
+ {
+ Integer.parseInt(nextOption);
+ }
+ catch (NumberFormatException e)
+ {
+ notFree = true;
+ }
+
+ // Add the option to the regular expression matcher if it is not a free argument definition.
+ if (notFree)
+ {
+ regexp += nextOption + (i.hasNext() ? "|" : "");
+ optionsAdded++;
+ }
+ }
+
+ // There has to be more that one option in the regular expression or else the compiler complains that the close
+ // cannot be nullable if the '?' token is used to make the matched option string optional.
+ regexp += ")" + ((optionsAdded > 0) ? "?" : "") + "(.*)";
+ Pattern pattern = Pattern.compile(regexp);
+
+ // Loop through all the command line arguments.
+ for (int i = 0; i < args.length; i++)
+ {
+ // Check if the next command line argument begins with a '-' character and is therefore the start of
+ // an option.
+ if (args[i].startsWith("-"))
+ {
+ // Extract the value of the option without the leading '-'.
+ String arg = args[i].substring(1);
+
+ // Match up to the longest matching option.
+ optionMatcher = pattern.matcher(arg);
+ optionMatcher.matches();
+
+ String matchedOption = optionMatcher.group(1);
+
+ // Match any argument directly appended onto the longest matching option.
+ String matchedArg = optionMatcher.group(2);
+
+ // Check that a known option was matched.
+ if ((matchedOption != null) && !"".equals(matchedOption))
+ {
+ // Get the command line option information for the matched option.
+ CommandLineOption optionInfo = optionMap.get(matchedOption);
+
+ // Check if this option is expecting arguments.
+ if (optionInfo.expectsArgs)
+ {
+ // The option is expecting arguments so swallow the next command line argument as an
+ // argument to this option.
+ expectingArgs = true;
+ optionExpectingArgs = matchedOption;
+
+ // In the mean time set this options argument to the empty string in case no argument is ever
+ // supplied.
+ // options.put(matchedOption, "");
+ }
+
+ // Check if the option was matched on its own and is a flag in which case set that flag.
+ if ("".equals(matchedArg) && !optionInfo.expectsArgs)
+ {
+ options.put(matchedOption, "true");
+ }
+ // The option was matched as a substring with its argument appended to it or is a flag that is
+ // condensed together with other flags.
+ else if (!"".equals(matchedArg))
+ {
+ // Check if the option is a flag and therefore is allowed to be condensed together
+ // with other flags.
+ if (!optionInfo.expectsArgs)
+ {
+ // Set the first matched flag.
+ options.put(matchedOption, "true");
+
+ // Repeat the longest matching process on the remainder but ensure that the remainder
+ // consists only of flags as only flags may be condensed together in this fashion.
+ do
+ {
+ // Match the remainder against the options.
+ optionMatcher = pattern.matcher(matchedArg);
+ optionMatcher.matches();
+
+ matchedOption = optionMatcher.group(1);
+ matchedArg = optionMatcher.group(2);
+
+ // Check that an option was matched.
+ if (matchedOption != null)
+ {
+ // Get the command line option information for the next matched option.
+ optionInfo = optionMap.get(matchedOption);
+
+ // Ensure that the next option is a flag or raise an error if not.
+ if (optionInfo.expectsArgs == true)
+ {
+ parsingErrors.add("Option " + matchedOption + " cannot be combined with flags.\n");
+ }
+
+ options.put(matchedOption, "true");
+ }
+ // The remainder could not be matched against a flag it is either an unknown flag
+ // or an illegal argument to a flag.
+ else
+ {
+ parsingErrors.add("Illegal argument to a flag in the option " + arg + "\n");
+
+ break;
+ }
+ }
+ // Continue until the remainder of the argument has all been matched with flags.
+ while (!"".equals(matchedArg));
+ }
+ // The option is expecting an argument, so store the unmatched portion against it
+ // as its argument.
+ else
+ {
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, matchedArg);
+
+ // Store the argument against its option (regardless of its format).
+ options.put(matchedOption, matchedArg);
+
+ // The argument to this flag has already been supplied to it. Do not swallow the
+ // next command line argument as an argument to this flag.
+ expectingArgs = false;
+ }
+ }
+ }
+ else // No matching option was found.
+ {
+ // Add this to the list of parsing errors if errors on unkowns is being used.
+ if (errorsOnUnknowns)
+ {
+ parsingErrors.add("Option " + matchedOption + " is not a recognized option.\n");
+ }
+ }
+ }
+ // The command line argument did not being with a '-' so it is an argument to the previous flag or it
+ // is a free argument.
+ else
+ {
+ // Check if a previous flag is expecting to swallow this next argument as its argument.
+ if (expectingArgs)
+ {
+ // Get the option info for the option waiting for arguments.
+ CommandLineOption optionInfo = optionMap.get(optionExpectingArgs);
+
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, args[i]);
+
+ // Store the argument against its option (regardless of its format).
+ options.put(optionExpectingArgs, args[i]);
+
+ // Clear the expecting args flag now that the argument has been swallowed.
+ expectingArgs = false;
+ optionExpectingArgs = null;
+ }
+ // This command line option is not an argument to any option. Add it to the set of 'free' options.
+ else
+ {
+ // Get the option info for the free option, if there is any.
+ CommandLineOption optionInfo = optionMap.get(Integer.toString(free));
+
+ if (optionInfo != null)
+ {
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, args[i]);
+ }
+
+ // Add to the list of free options.
+ options.put(Integer.toString(free), args[i]);
+
+ // Move on to the next free argument.
+ free++;
+ }
+ }
+ }
+
+ // Scan through all the specified options to check that all mandatory options have been set and that all flags
+ // that were not set are set to false in the set of properties.
+ for (CommandLineOption optionInfo : optionMap.values())
+ {
+ // Check if this is a flag.
+ if (!optionInfo.expectsArgs)
+ {
+ // Check if the flag is not set in the properties and set it to false if so.
+ if (!options.containsKey(optionInfo.option))
+ {
+ options.put(optionInfo.option, "false");
+ }
+ }
+ // Check if this is a mandatory option and was not set.
+ else if (optionInfo.mandatory && !options.containsKey(optionInfo.option))
+ {
+ // Create an error for the missing option.
+ parsingErrors.add("Option " + optionInfo.option + " is mandatory but not was not specified.\n");
+ }
+ }
+
+ // Check if there were any errors.
+ if (!parsingErrors.isEmpty())
+ {
+ // Throw an illegal argument exception to signify that there were parsing errors.
+ throw new IllegalArgumentException();
+ }
+
+ // Convert any name/value pairs in the free arguments into properties in the parsed options.
+ options = takeFreeArgsAsProperties(options, 1);
+
+ parsedProperties = options;
+
+ return options;
+ }
+
+ /**
+ * If a command line has been parsed, calling this method sets all of its parsed options into the specified properties.
+ */
+ public void addCommandLineToProperties(Properties properties)
+ {
+ if (parsedProperties != null)
+ {
+ for (Object propKey : parsedProperties.keySet())
+ {
+ String name = (String) propKey;
+ String value = parsedProperties.getProperty(name);
+
+ properties.setProperty(name, value);
+ }
+ }
+ }
+
+ /**
+ * Resets this command line parser after it has been used to parse a command line. This method will only need
+ * to be called to use this parser a second time which is not likely seeing as a command line is usually only
+ * specified once. However, it is exposed as a public method for the rare case where this may be done.
+ *
+ * <p/>Cleans the internal state of this parser, removing all stored errors and information about the options in
+ * force.
+ */
+ public void reset()
+ {
+ parsingErrors = new ArrayList<String>();
+ parsedProperties = null;
+ }
+
+ /**
+ * Adds the option to list of available command line options.
+ *
+ * @param option The option to add as an available command line option.
+ * @param comment A comment for the option.
+ * @param argument The text that appears after the option in the usage string.
+ * @param mandatory When true, indicates that this option is mandatory.
+ * @param formatRegexp The format that the argument must take, defined as a regular expression.
+ */
+ protected void addOption(String option, String comment, String argument, boolean mandatory, String formatRegexp)
+ {
+ // Check if usage text has been set in which case this option is expecting arguments.
+ boolean expectsArgs = ((argument == null) || argument.equals("")) ? false : true;
+
+ // Add the option to the map of command line options.
+ CommandLineOption opt = new CommandLineOption(option, expectsArgs, comment, argument, mandatory, formatRegexp);
+ optionMap.put(option, opt);
+ }
+
+ /**
+ * Converts the free arguments into property declarations. After parsing the command line the free arguments
+ * are numbered from 1, such that the parsed properties contain values for the keys "1", "2", ... This method
+ * converts any free arguments declared using the 'name=value' syntax into properties with key 'name', value
+ * 'value'.
+ *
+ * <p/>For example the comand line:
+ * <pre>
+ * ... debug=true
+ * </pre>
+ *
+ * <p/>After parsing has properties:
+ * <pre>[[1, debug=true]]</pre>
+ *
+ * <p/>After applying this method the properties are:
+ * <pre>[[1, debug=true], [debug, true]]</pre>
+ *
+ * @param properties The parsed command line properties.
+ * @param from The free argument index to convert to properties from.
+ *
+ * @return The parsed command line properties, with free argument name value pairs too.
+ */
+ private Properties takeFreeArgsAsProperties(Properties properties, int from)
+ {
+ for (int i = from; true; i++)
+ {
+ String nextFreeArg = properties.getProperty(Integer.toString(i));
+
+ // Terminate the loop once all free arguments have been consumed.
+ if (nextFreeArg == null)
+ {
+ break;
+ }
+
+ // Split it on the =, strip any whitespace and set it as a system property.
+ String[] nameValuePair = nextFreeArg.split("=");
+
+ if (nameValuePair.length == 2)
+ {
+ properties.setProperty(nameValuePair[0], nameValuePair[1]);
+ }
+ }
+
+ return properties;
+ }
+
+ /**
+ * Checks the format of an argument to an option against its specified regular expression format if one has
+ * been set. Any errors are added to the list of parsing errors.
+ *
+ * @param optionInfo The command line option information for the option which is havings its argument checked.
+ * @param matchedArg The string argument to the option.
+ */
+ private void checkArgumentFormat(CommandLineOption optionInfo, String matchedArg)
+ {
+ // Check if this option enforces a format for its argument.
+ if (optionInfo.argumentFormatRegexp != null)
+ {
+ Pattern pattern = Pattern.compile(optionInfo.argumentFormatRegexp);
+ Matcher argumentMatcher = pattern.matcher(matchedArg);
+
+ // Check if the argument does not meet its required format.
+ if (!argumentMatcher.matches())
+ {
+ // Create an error for this badly formed argument.
+ parsingErrors.add("The argument to option " + optionInfo.option + " does not meet its required format.\n");
+ }
+ }
+ }
+
+ /**
+ * Extracts all name=value pairs from the command line, sets them all as system properties and also returns
+ * a map of properties containing them.
+ *
+ * @param args The command line.
+ * @param commandLine The command line parser.
+ * @param properties The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
+ *
+ * @return A set of properties containing all name=value pairs from the command line.
+ */
+ public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
+ {
+ // Capture the command line arguments or display errors and correct usage and then exit.
+ Properties options = null;
+
+ try
+ {
+ options = commandLine.parseCommandLine(args);
+
+ // Add all the trailing command line options (name=value pairs) to system properties. They may be picked up
+ // from there.
+ commandLine.addCommandLineToProperties(properties);
+ }
+ catch (IllegalArgumentException e)
+ {
+ System.out.println(commandLine.getErrors());
+ System.out.println(commandLine.getUsage());
+ System.exit(1);
+ }
+
+ return options;
+ }
+
+ /**
+ * Holds information about a command line options. This includes what its name is, whether or not it is a flag,
+ * whether or not it is mandatory, what its user comment is, what its argument reminder text is and what its
+ * regular expression format is.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Hold details of a command line option.
+ * </table>
+ */
+ protected class CommandLineOption
+ {
+ /** Holds the text for the flag to match this argument with. */
+ public String option = null;
+
+ /** Holds a string describing how to use this command line argument. */
+ public String argument = null;
+
+ /** Flag that determines whether or not this command line argument can take arguments. */
+ public boolean expectsArgs = false;
+
+ /** Holds a short comment describing what this command line argument is for. */
+ public String comment = null;
+
+ /** Flag that determines whether or not this is an mandatory command line argument. */
+ public boolean mandatory = false;
+
+ /** A regular expression describing what format the argument to this option muist have. */
+ public String argumentFormatRegexp = null;
+
+ /**
+ * Create a command line option object that holds specific information about a command line option.
+ *
+ * @param option The text that matches the option.
+ * @param expectsArgs Whether or not the option expects arguments. It is a flag if this is false.
+ * @param comment A comment explaining how to use this option.
+ * @param argument A short reminder of the format of the argument to this option/
+ * @param mandatory Set to true if this option is mandatory.
+ * @param formatRegexp The regular expression that the argument to this option must meet to be valid.
+ */
+ public CommandLineOption(String option, boolean expectsArgs, String comment, String argument, boolean mandatory,
+ String formatRegexp)
+ {
+ this.option = option;
+ this.expectsArgs = expectsArgs;
+ this.comment = comment;
+ this.argument = argument;
+ this.mandatory = mandatory;
+ this.argumentFormatRegexp = formatRegexp;
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
index 3b8ebc1666..7494745457 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/FileUtils.java
@@ -1,195 +1,195 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-import java.io.*;
-
-/**
- * FileUtils provides some simple helper methods for working with files. It follows the convention of wrapping all
- * checked exceptions as runtimes, so code using these methods is free of try-catch blocks but does not expect to
- * recover from errors.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Read a text file as a string.
- * <tr><td> Open a file or default resource as an input stream.
- * </table>
- */
-public class FileUtils
-{
- /**
- * Reads a text file as a string.
- *
- * @param filename The name of the file.
- *
- * @return The contents of the file.
- */
- public static String readFileAsString(String filename)
- {
- BufferedInputStream is = null;
-
- try
- {
- is = new BufferedInputStream(new FileInputStream(filename));
- }
- catch (FileNotFoundException e)
- {
- throw new RuntimeException(e);
- }
-
- return readStreamAsString(is);
- }
-
- /**
- * Reads a text file as a string.
- *
- * @param file The file.
- *
- * @return The contents of the file.
- */
- public static String readFileAsString(File file)
- {
- BufferedInputStream is = null;
-
- try
- {
- is = new BufferedInputStream(new FileInputStream(file));
- }
- catch (FileNotFoundException e)
- {
- throw new RuntimeException(e);
- }
-
- return readStreamAsString(is);
- }
-
- /**
- * Reads the contents of a reader, one line at a time until the end of stream is encountered, and returns all
- * together as a string.
- *
- * @param is The reader.
- *
- * @return The contents of the reader.
- */
- private static String readStreamAsString(BufferedInputStream is)
- {
- try
- {
- byte[] data = new byte[4096];
-
- StringBuffer inBuffer = new StringBuffer();
-
- String line;
- int read;
-
- while ((read = is.read(data)) != -1)
- {
- String s = new String(data, 0, read);
- inBuffer.append(s);
- }
-
- return inBuffer.toString();
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Either opens the specified filename as an input stream, or uses the default resource loaded using the
- * specified class loader, if opening the file fails or no file name is specified.
- *
- * @param filename The name of the file to open.
- * @param defaultResource The name of the default resource on the classpath if the file cannot be opened.
- * @param cl The classloader to load the default resource with.
- *
- * @return An input stream for the file or resource, or null if one could not be opened.
- */
- public static InputStream openFileOrDefaultResource(String filename, String defaultResource, ClassLoader cl)
- {
- InputStream is = null;
-
- // Flag to indicate whether the default resource should be used. By default this is true, so that the default
- // is used when opening the file fails.
- boolean useDefault = true;
-
- // Try to open the file if one was specified.
- if (filename != null)
- {
- try
- {
- is = new BufferedInputStream(new FileInputStream(new File(filename)));
-
- // Clear the default flag because the file was succesfully opened.
- useDefault = false;
- }
- catch (FileNotFoundException e)
- {
- // Ignore this exception, the default will be used instead.
- }
- }
-
- // Load the default resource if a file was not specified, or if opening the file failed.
- if (useDefault)
- {
- is = cl.getResourceAsStream(defaultResource);
- }
-
- return is;
- }
-
- /**
- * Copies the specified source file to the specified destintaion file. If the destinationst file does not exist,
- * it is created.
- *
- * @param src The source file name.
- * @param dst The destination file name.
- */
- public static void copy(File src, File dst)
- {
- try
- {
- InputStream in = new FileInputStream(src);
- if (!dst.exists())
- {
- dst.createNewFile();
- }
-
- OutputStream out = new FileOutputStream(dst);
-
- // Transfer bytes from in to out
- byte[] buf = new byte[1024];
- int len;
- while ((len = in.read(buf)) > 0)
- {
- out.write(buf, 0, len);
- }
-
- in.close();
- out.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.io.*;
+
+/**
+ * FileUtils provides some simple helper methods for working with files. It follows the convention of wrapping all
+ * checked exceptions as runtimes, so code using these methods is free of try-catch blocks but does not expect to
+ * recover from errors.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Read a text file as a string.
+ * <tr><td> Open a file or default resource as an input stream.
+ * </table>
+ */
+public class FileUtils
+{
+ /**
+ * Reads a text file as a string.
+ *
+ * @param filename The name of the file.
+ *
+ * @return The contents of the file.
+ */
+ public static String readFileAsString(String filename)
+ {
+ BufferedInputStream is = null;
+
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(filename));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return readStreamAsString(is);
+ }
+
+ /**
+ * Reads a text file as a string.
+ *
+ * @param file The file.
+ *
+ * @return The contents of the file.
+ */
+ public static String readFileAsString(File file)
+ {
+ BufferedInputStream is = null;
+
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(file));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return readStreamAsString(is);
+ }
+
+ /**
+ * Reads the contents of a reader, one line at a time until the end of stream is encountered, and returns all
+ * together as a string.
+ *
+ * @param is The reader.
+ *
+ * @return The contents of the reader.
+ */
+ private static String readStreamAsString(BufferedInputStream is)
+ {
+ try
+ {
+ byte[] data = new byte[4096];
+
+ StringBuffer inBuffer = new StringBuffer();
+
+ String line;
+ int read;
+
+ while ((read = is.read(data)) != -1)
+ {
+ String s = new String(data, 0, read);
+ inBuffer.append(s);
+ }
+
+ return inBuffer.toString();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Either opens the specified filename as an input stream, or uses the default resource loaded using the
+ * specified class loader, if opening the file fails or no file name is specified.
+ *
+ * @param filename The name of the file to open.
+ * @param defaultResource The name of the default resource on the classpath if the file cannot be opened.
+ * @param cl The classloader to load the default resource with.
+ *
+ * @return An input stream for the file or resource, or null if one could not be opened.
+ */
+ public static InputStream openFileOrDefaultResource(String filename, String defaultResource, ClassLoader cl)
+ {
+ InputStream is = null;
+
+ // Flag to indicate whether the default resource should be used. By default this is true, so that the default
+ // is used when opening the file fails.
+ boolean useDefault = true;
+
+ // Try to open the file if one was specified.
+ if (filename != null)
+ {
+ try
+ {
+ is = new BufferedInputStream(new FileInputStream(new File(filename)));
+
+ // Clear the default flag because the file was succesfully opened.
+ useDefault = false;
+ }
+ catch (FileNotFoundException e)
+ {
+ // Ignore this exception, the default will be used instead.
+ }
+ }
+
+ // Load the default resource if a file was not specified, or if opening the file failed.
+ if (useDefault)
+ {
+ is = cl.getResourceAsStream(defaultResource);
+ }
+
+ return is;
+ }
+
+ /**
+ * Copies the specified source file to the specified destintaion file. If the destinationst file does not exist,
+ * it is created.
+ *
+ * @param src The source file name.
+ * @param dst The destination file name.
+ */
+ public static void copy(File src, File dst)
+ {
+ try
+ {
+ InputStream in = new FileInputStream(src);
+ if (!dst.exists())
+ {
+ dst.createNewFile();
+ }
+
+ OutputStream out = new FileOutputStream(dst);
+
+ // Transfer bytes from in to out
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0)
+ {
+ out.write(buf, 0, len);
+ }
+
+ in.close();
+ out.close();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java
index 10f6a27293..4677713dc9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/PrettyPrintingUtils.java
@@ -1,75 +1,75 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-/**
- * Contains pretty printing convenienve methods for producing formatted logging output, mostly for debugging purposes.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @todo Drop this. There are already array pretty printing methods it java.utils.Arrays.
- */
-public class PrettyPrintingUtils
-{
- /**
- * Pretty prints an array of ints as a string.
- *
- * @param array The array to pretty print.
- *
- * @return The pretty printed string.
- */
- public static String printArray(int[] array)
- {
- String result = "[";
- for (int i = 0; i < array.length; i++)
- {
- result += array[i];
- result += (i < (array.length - 1)) ? ", " : "";
- }
-
- result += "]";
-
- return result;
- }
-
- /**
- * Pretty prints an array of strings as a string.
- *
- * @param array The array to pretty print.
- *
- * @return The pretty printed string.
- */
- public static String printArray(String[] array)
- {
- String result = "[";
- for (int i = 0; i < array.length; i++)
- {
- result += array[i];
- result += (i < (array.length - 1)) ? ", " : "";
- }
-
- result += "]";
-
- return result;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+/**
+ * Contains pretty printing convenienve methods for producing formatted logging output, mostly for debugging purposes.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @todo Drop this. There are already array pretty printing methods it java.utils.Arrays.
+ */
+public class PrettyPrintingUtils
+{
+ /**
+ * Pretty prints an array of ints as a string.
+ *
+ * @param array The array to pretty print.
+ *
+ * @return The pretty printed string.
+ */
+ public static String printArray(int[] array)
+ {
+ String result = "[";
+ for (int i = 0; i < array.length; i++)
+ {
+ result += array[i];
+ result += (i < (array.length - 1)) ? ", " : "";
+ }
+
+ result += "]";
+
+ return result;
+ }
+
+ /**
+ * Pretty prints an array of strings as a string.
+ *
+ * @param array The array to pretty print.
+ *
+ * @return The pretty printed string.
+ */
+ public static String printArray(String[] array)
+ {
+ String result = "[";
+ for (int i = 0; i < array.length; i++)
+ {
+ result += array[i];
+ result += (i < (array.length - 1)) ? ", " : "";
+ }
+
+ result += "]";
+
+ return result;
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/PropertiesUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/PropertiesUtils.java
index 63cf6f252b..d90e3b1a17 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/PropertiesUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/PropertiesUtils.java
@@ -1,200 +1,200 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Iterator;
-import java.util.Properties;
-
-/**
- * PropertiesHelper defines some static methods which are useful when working with properties
- * files.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Read properties from an input stream
- * <tr><td> Read properties from a file
- * <tr><td> Read properties from a URL
- * <tr><td> Read properties given a path to a file
- * <tr><td> Trim any whitespace from property values
- * </table>
- */
-public class PropertiesUtils
-{
- /** Used for logging. */
- private static final Logger log = LoggerFactory.getLogger(PropertiesUtils.class);
-
- /**
- * Get properties from an input stream.
- *
- * @param is The input stream.
- *
- * @return The properties loaded from the input stream.
- *
- * @throws IOException If the is an I/O error reading from the stream.
- */
- public static Properties getProperties(InputStream is) throws IOException
- {
- log.debug("getProperties(InputStream): called");
-
- // Create properties object laoded from input stream
- Properties properties = new Properties();
-
- properties.load(is);
-
- return properties;
- }
-
- /**
- * Get properties from a file.
- *
- * @param file The file.
- *
- * @return The properties loaded from the file.
- *
- * @throws IOException If there is an I/O error reading from the file.
- */
- public static Properties getProperties(File file) throws IOException
- {
- log.debug("getProperties(File): called");
-
- // Open the file as an input stream
- InputStream is = new FileInputStream(file);
-
- // Create properties object loaded from the stream
- Properties properties = getProperties(is);
-
- // Close the file
- is.close();
-
- return properties;
- }
-
- /**
- * Get properties from a url.
- *
- * @param url The URL.
- *
- * @return The properties loaded from the url.
- *
- * @throws IOException If there is an I/O error reading from the URL.
- */
- public static Properties getProperties(URL url) throws IOException
- {
- log.debug("getProperties(URL): called");
-
- // Open the URL as an input stream
- InputStream is = url.openStream();
-
- // Create properties object loaded from the stream
- Properties properties = getProperties(is);
-
- // Close the url
- is.close();
-
- return properties;
- }
-
- /**
- * Get properties from a path name. The path name may refer to either a file or a URL.
- *
- * @param pathname The path name.
- *
- * @return The properties loaded from the file or URL.
- *
- * @throws IOException If there is an I/O error reading from the URL or file named by the path.
- */
- public static Properties getProperties(String pathname) throws IOException
- {
- log.debug("getProperties(String): called");
-
- // Check that the path is not null
- if (pathname == null)
- {
- return null;
- }
-
- // Check if the path is a URL
- if (isURL(pathname))
- {
- // The path is a URL
- return getProperties(new URL(pathname));
- }
- else
- {
- // Assume the path is a file name
- return getProperties(new File(pathname));
- }
- }
-
- /**
- * Trims whitespace from property values. This method returns a new set of properties
- * the same as the properties specified as an argument but with any white space removed by
- * the {@link java.lang.String#trim} method.
- *
- * @param properties The properties to trim whitespace from.
- *
- * @return The white space trimmed properties.
- */
- public static Properties trim(Properties properties)
- {
- Properties trimmedProperties = new Properties();
-
- // Loop over all the properties
- for (Iterator i = properties.keySet().iterator(); i.hasNext();)
- {
- String next = (String) i.next();
- String nextValue = properties.getProperty(next);
-
- // Trim the value if it is not null
- if (nextValue != null)
- {
- nextValue.trim();
- }
-
- // Store the trimmed value in the trimmed properties
- trimmedProperties.setProperty(next, nextValue);
- }
-
- return trimmedProperties;
- }
-
- /**
- * Helper method. Guesses whether a string is a URL or not. A String is considered to be a url if it begins with
- * http:, ftp:, or uucp:.
- *
- * @param name The string to test for being a URL.
- *
- * @return True if the string is a URL and false if not.
- */
- private static boolean isURL(String name)
- {
- return (name.toLowerCase().startsWith("http:") || name.toLowerCase().startsWith("ftp:")
- || name.toLowerCase().startsWith("uucp:"));
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Properties;
+
+/**
+ * PropertiesHelper defines some static methods which are useful when working with properties
+ * files.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Read properties from an input stream
+ * <tr><td> Read properties from a file
+ * <tr><td> Read properties from a URL
+ * <tr><td> Read properties given a path to a file
+ * <tr><td> Trim any whitespace from property values
+ * </table>
+ */
+public class PropertiesUtils
+{
+ /** Used for logging. */
+ private static final Logger log = LoggerFactory.getLogger(PropertiesUtils.class);
+
+ /**
+ * Get properties from an input stream.
+ *
+ * @param is The input stream.
+ *
+ * @return The properties loaded from the input stream.
+ *
+ * @throws IOException If the is an I/O error reading from the stream.
+ */
+ public static Properties getProperties(InputStream is) throws IOException
+ {
+ log.debug("getProperties(InputStream): called");
+
+ // Create properties object laoded from input stream
+ Properties properties = new Properties();
+
+ properties.load(is);
+
+ return properties;
+ }
+
+ /**
+ * Get properties from a file.
+ *
+ * @param file The file.
+ *
+ * @return The properties loaded from the file.
+ *
+ * @throws IOException If there is an I/O error reading from the file.
+ */
+ public static Properties getProperties(File file) throws IOException
+ {
+ log.debug("getProperties(File): called");
+
+ // Open the file as an input stream
+ InputStream is = new FileInputStream(file);
+
+ // Create properties object loaded from the stream
+ Properties properties = getProperties(is);
+
+ // Close the file
+ is.close();
+
+ return properties;
+ }
+
+ /**
+ * Get properties from a url.
+ *
+ * @param url The URL.
+ *
+ * @return The properties loaded from the url.
+ *
+ * @throws IOException If there is an I/O error reading from the URL.
+ */
+ public static Properties getProperties(URL url) throws IOException
+ {
+ log.debug("getProperties(URL): called");
+
+ // Open the URL as an input stream
+ InputStream is = url.openStream();
+
+ // Create properties object loaded from the stream
+ Properties properties = getProperties(is);
+
+ // Close the url
+ is.close();
+
+ return properties;
+ }
+
+ /**
+ * Get properties from a path name. The path name may refer to either a file or a URL.
+ *
+ * @param pathname The path name.
+ *
+ * @return The properties loaded from the file or URL.
+ *
+ * @throws IOException If there is an I/O error reading from the URL or file named by the path.
+ */
+ public static Properties getProperties(String pathname) throws IOException
+ {
+ log.debug("getProperties(String): called");
+
+ // Check that the path is not null
+ if (pathname == null)
+ {
+ return null;
+ }
+
+ // Check if the path is a URL
+ if (isURL(pathname))
+ {
+ // The path is a URL
+ return getProperties(new URL(pathname));
+ }
+ else
+ {
+ // Assume the path is a file name
+ return getProperties(new File(pathname));
+ }
+ }
+
+ /**
+ * Trims whitespace from property values. This method returns a new set of properties
+ * the same as the properties specified as an argument but with any white space removed by
+ * the {@link java.lang.String#trim} method.
+ *
+ * @param properties The properties to trim whitespace from.
+ *
+ * @return The white space trimmed properties.
+ */
+ public static Properties trim(Properties properties)
+ {
+ Properties trimmedProperties = new Properties();
+
+ // Loop over all the properties
+ for (Iterator i = properties.keySet().iterator(); i.hasNext();)
+ {
+ String next = (String) i.next();
+ String nextValue = properties.getProperty(next);
+
+ // Trim the value if it is not null
+ if (nextValue != null)
+ {
+ nextValue.trim();
+ }
+
+ // Store the trimmed value in the trimmed properties
+ trimmedProperties.setProperty(next, nextValue);
+ }
+
+ return trimmedProperties;
+ }
+
+ /**
+ * Helper method. Guesses whether a string is a URL or not. A String is considered to be a url if it begins with
+ * http:, ftp:, or uucp:.
+ *
+ * @param name The string to test for being a URL.
+ *
+ * @return True if the string is a URL and false if not.
+ */
+ private static boolean isURL(String name)
+ {
+ return (name.toLowerCase().startsWith("http:") || name.toLowerCase().startsWith("ftp:")
+ || name.toLowerCase().startsWith("uucp:"));
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java
index 495918911a..28fb2e0c8a 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java
@@ -1,228 +1,228 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Provides helper methods for operating on classes and methods using reflection. Reflection methods tend to return
- * a lot of checked exception so writing code to use them can be tedious and harder to read, especially when such errors
- * are not expected to occur. This class always works with {@link ReflectionUtilsException}, which is a runtime exception,
- * to wrap the checked exceptions raised by the standard Java reflection methods. Code using it does not normally
- * expect these errors to occur, usually does not have a recovery mechanism for them when they do, but is cleaner,
- * quicker to write and easier to read in the majority of cases.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Look up Classes by name.
- * <tr><td> Instantiate Classes by no-arg constructor.
- * </table>
- */
-public class ReflectionUtils
-{
- /**
- * Gets the Class object for a named class.
- *
- * @param className The class to get the Class object for.
- *
- * @return The Class object for the named class.
- */
- public static Class<?> forName(String className)
- {
- try
- {
- return Class.forName(className);
- }
- catch (ClassNotFoundException e)
- {
- throw new ReflectionUtilsException("ClassNotFoundException whilst finding class.", e);
- }
- }
-
- /**
- * Creates an instance of a Class, instantiated through its no-args constructor.
- *
- * @param cls The Class to instantiate.
- * @param <T> The Class type.
- *
- * @return An instance of the class.
- */
- public static <T> T newInstance(Class<? extends T> cls)
- {
- try
- {
- return cls.newInstance();
- }
- catch (InstantiationException e)
- {
- throw new ReflectionUtilsException("InstantiationException whilst instantiating class.", e);
- }
- catch (IllegalAccessException e)
- {
- throw new ReflectionUtilsException("IllegalAccessException whilst instantiating class.", e);
- }
- }
-
- /**
- * Calls a named method on an object with a specified set of parameters, any Java access modifier are overridden.
- *
- * @param o The object to call.
- * @param method The method name to call.
- * @param params The parameters to pass.
- * @param paramClasses The argument types.
- *
- * @return The return value from the method call.
- */
- public static Object callMethodOverridingIllegalAccess(Object o, String method, Object[] params, Class[] paramClasses)
- {
- // Get the objects class.
- Class cls = o.getClass();
-
- // Get the classes of the parameters.
- /*Class[] paramClasses = new Class[params.length];
-
- for (int i = 0; i < params.length; i++)
- {
- paramClasses[i] = params[i].getClass();
- }*/
-
- try
- {
- // Try to find the matching method on the class.
- Method m = cls.getDeclaredMethod(method, paramClasses);
-
- // Make it accessible.
- m.setAccessible(true);
-
- // Invoke it with the parameters.
- return m.invoke(o, params);
- }
- catch (NoSuchMethodException e)
- {
- throw new ReflectionUtilsException("NoSuchMethodException.", e);
- }
- catch (IllegalAccessException e)
- {
- throw new ReflectionUtilsException("IllegalAccessException.", e);
- }
- catch (InvocationTargetException e)
- {
- throw new ReflectionUtilsException("InvocationTargetException", e);
- }
- }
-
- /**
- * Calls a named method on an object with a specified set of parameters.
- *
- * @param o The object to call.
- * @param method The method name to call.
- * @param params The parameters to pass.
- *
- * @return The return value from the method call.
- */
- public static Object callMethod(Object o, String method, Object[] params)
- {
- // Get the objects class.
- Class cls = o.getClass();
-
- // Get the classes of the parameters.
- Class[] paramClasses = new Class[params.length];
-
- for (int i = 0; i < params.length; i++)
- {
- paramClasses[i] = params[i].getClass();
- }
-
- try
- {
- // Try to find the matching method on the class.
- Method m = cls.getMethod(method, paramClasses);
-
- // Invoke it with the parameters.
- return m.invoke(o, params);
- }
- catch (NoSuchMethodException e)
- {
- throw new ReflectionUtilsException("NoSuchMethodException.", e);
- }
- catch (IllegalAccessException e)
- {
- throw new ReflectionUtilsException("IllegalAccessException", e);
- }
- catch (InvocationTargetException e)
- {
- throw new ReflectionUtilsException("InvocationTargetException", e);
- }
- }
-
- /**
- * Calls a constuctor witht the specified arguments.
- *
- * @param constructor The constructor.
- * @param args The arguments.
- * @param <T> The Class type.
- *
- * @return An instance of the class that the constructor is for.
- */
- public static <T> T newInstance(Constructor<T> constructor, Object[] args)
- {
- try
- {
- return constructor.newInstance(args);
- }
- catch (InstantiationException e)
- {
- throw new ReflectionUtilsException("InstantiationException", e);
- }
- catch (IllegalAccessException e)
- {
- throw new ReflectionUtilsException("IllegalAccessException", e);
- }
- catch (InvocationTargetException e)
- {
- throw new ReflectionUtilsException("InvocationTargetException", e);
- }
- }
-
- /**
- * Gets the constructor of a class that takes the specified set of arguments if any matches. If no matching
- * constructor is found then a runtime exception is raised.
- *
- * @param cls The class to get a constructor from.
- * @param args The arguments to match.
- * @param <T> The class type.
- *
- * @return The constructor.
- */
- public static <T> Constructor<T> getConstructor(Class<T> cls, Class[] args)
- {
- try
- {
- return cls.getConstructor(args);
- }
- catch (NoSuchMethodException e)
- {
- throw new ReflectionUtilsException("NoSuchMethodException", e);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Provides helper methods for operating on classes and methods using reflection. Reflection methods tend to return
+ * a lot of checked exception so writing code to use them can be tedious and harder to read, especially when such errors
+ * are not expected to occur. This class always works with {@link ReflectionUtilsException}, which is a runtime exception,
+ * to wrap the checked exceptions raised by the standard Java reflection methods. Code using it does not normally
+ * expect these errors to occur, usually does not have a recovery mechanism for them when they do, but is cleaner,
+ * quicker to write and easier to read in the majority of cases.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Look up Classes by name.
+ * <tr><td> Instantiate Classes by no-arg constructor.
+ * </table>
+ */
+public class ReflectionUtils
+{
+ /**
+ * Gets the Class object for a named class.
+ *
+ * @param className The class to get the Class object for.
+ *
+ * @return The Class object for the named class.
+ */
+ public static Class<?> forName(String className)
+ {
+ try
+ {
+ return Class.forName(className);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new ReflectionUtilsException("ClassNotFoundException whilst finding class.", e);
+ }
+ }
+
+ /**
+ * Creates an instance of a Class, instantiated through its no-args constructor.
+ *
+ * @param cls The Class to instantiate.
+ * @param <T> The Class type.
+ *
+ * @return An instance of the class.
+ */
+ public static <T> T newInstance(Class<? extends T> cls)
+ {
+ try
+ {
+ return cls.newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ throw new ReflectionUtilsException("InstantiationException whilst instantiating class.", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionUtilsException("IllegalAccessException whilst instantiating class.", e);
+ }
+ }
+
+ /**
+ * Calls a named method on an object with a specified set of parameters, any Java access modifier are overridden.
+ *
+ * @param o The object to call.
+ * @param method The method name to call.
+ * @param params The parameters to pass.
+ * @param paramClasses The argument types.
+ *
+ * @return The return value from the method call.
+ */
+ public static Object callMethodOverridingIllegalAccess(Object o, String method, Object[] params, Class[] paramClasses)
+ {
+ // Get the objects class.
+ Class cls = o.getClass();
+
+ // Get the classes of the parameters.
+ /*Class[] paramClasses = new Class[params.length];
+
+ for (int i = 0; i < params.length; i++)
+ {
+ paramClasses[i] = params[i].getClass();
+ }*/
+
+ try
+ {
+ // Try to find the matching method on the class.
+ Method m = cls.getDeclaredMethod(method, paramClasses);
+
+ // Make it accessible.
+ m.setAccessible(true);
+
+ // Invoke it with the parameters.
+ return m.invoke(o, params);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ReflectionUtilsException("NoSuchMethodException.", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionUtilsException("IllegalAccessException.", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new ReflectionUtilsException("InvocationTargetException", e);
+ }
+ }
+
+ /**
+ * Calls a named method on an object with a specified set of parameters.
+ *
+ * @param o The object to call.
+ * @param method The method name to call.
+ * @param params The parameters to pass.
+ *
+ * @return The return value from the method call.
+ */
+ public static Object callMethod(Object o, String method, Object[] params)
+ {
+ // Get the objects class.
+ Class cls = o.getClass();
+
+ // Get the classes of the parameters.
+ Class[] paramClasses = new Class[params.length];
+
+ for (int i = 0; i < params.length; i++)
+ {
+ paramClasses[i] = params[i].getClass();
+ }
+
+ try
+ {
+ // Try to find the matching method on the class.
+ Method m = cls.getMethod(method, paramClasses);
+
+ // Invoke it with the parameters.
+ return m.invoke(o, params);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ReflectionUtilsException("NoSuchMethodException.", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionUtilsException("IllegalAccessException", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new ReflectionUtilsException("InvocationTargetException", e);
+ }
+ }
+
+ /**
+ * Calls a constuctor witht the specified arguments.
+ *
+ * @param constructor The constructor.
+ * @param args The arguments.
+ * @param <T> The Class type.
+ *
+ * @return An instance of the class that the constructor is for.
+ */
+ public static <T> T newInstance(Constructor<T> constructor, Object[] args)
+ {
+ try
+ {
+ return constructor.newInstance(args);
+ }
+ catch (InstantiationException e)
+ {
+ throw new ReflectionUtilsException("InstantiationException", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ReflectionUtilsException("IllegalAccessException", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new ReflectionUtilsException("InvocationTargetException", e);
+ }
+ }
+
+ /**
+ * Gets the constructor of a class that takes the specified set of arguments if any matches. If no matching
+ * constructor is found then a runtime exception is raised.
+ *
+ * @param cls The class to get a constructor from.
+ * @param args The arguments to match.
+ * @param <T> The class type.
+ *
+ * @return The constructor.
+ */
+ public static <T> Constructor<T> getConstructor(Class<T> cls, Class[] args)
+ {
+ try
+ {
+ return cls.getConstructor(args);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new ReflectionUtilsException("NoSuchMethodException", e);
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java b/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java
index 20499641ac..c2862a755b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java
@@ -1,44 +1,44 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.util;
-
-/**
- * Wraps a checked exception that occurs when {@link ReflectionUtils} encounters checked exceptions using standard
- * Java reflection methods.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Wrap a checked reflection exception.
- * </table>
- */
-public class ReflectionUtilsException extends RuntimeException
-{
- /**
- * Creates a runtime reflection exception, from a checked one.
- *
- * @param message The message.
- * @param cause The causing exception.
- */
- public ReflectionUtilsException(String message, Throwable cause)
- {
- super(message, cause);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.util;
+
+/**
+ * Wraps a checked exception that occurs when {@link ReflectionUtils} encounters checked exceptions using standard
+ * Java reflection methods.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Wrap a checked reflection exception.
+ * </table>
+ */
+public class ReflectionUtilsException extends RuntimeException
+{
+ /**
+ * Creates a runtime reflection exception, from a checked one.
+ *
+ * @param message The message.
+ * @param cause The causing exception.
+ */
+ public ReflectionUtilsException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/AlreadyUnblockedException.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/AlreadyUnblockedException.java
index 4acea0e2ec..ef43d1c8a8 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/AlreadyUnblockedException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/AlreadyUnblockedException.java
@@ -1,13 +1,13 @@
-package org.apache.qpid.util.concurrent;
-
-/**
- * Used to signal that a data element and its producer cannot be requeued or sent an error message when using a
- * {@link BatchSynchQueue} because the producer has already been unblocked by an unblocking take on the queue.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Signal that an unblocking take has already occurred.
- * </table>
- */
-public class AlreadyUnblockedException extends RuntimeException
-{ }
+package org.apache.qpid.util.concurrent;
+
+/**
+ * Used to signal that a data element and its producer cannot be requeued or sent an error message when using a
+ * {@link BatchSynchQueue} because the producer has already been unblocked by an unblocking take on the queue.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Signal that an unblocking take has already occurred.
+ * </table>
+ */
+public class AlreadyUnblockedException extends RuntimeException
+{ }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueue.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueue.java
index cf2abfffb8..261eecb561 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueue.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueue.java
@@ -1,101 +1,101 @@
-package org.apache.qpid.util.concurrent;
-
-import java.util.Collection;
-import java.util.concurrent.BlockingQueue;
-
-/**
- * BatchSynchQueue is an abstraction of the classic producer/consumer buffer pattern for thread interaction. In this
- * pattern threads can deposit data onto a buffer whilst other threads take data from the buffer and perform usefull
- * work with it. A BatchSynchQueue adds to this the possibility that producers can be blocked until their data is
- * consumed or until a consumer chooses to release the producer some time after consuming the data from the queue.
- *
- * <p>There are a number of possible advantages to using this technique when compared with having the producers
- * processing their own data:
- *
- * <ul>
- * <li>Data may be deposited asynchronously in the buffer allowing the producers to continue running.</li>
- * <li>Data may be deposited synchronously in the buffer so that producers wait until their data has been processed
- * before being allowed to continue.</li>
- * <li>Variable rates of production/consumption can be smoothed over by the buffer as it provides space in memory to
- * hold data between production and consumption.</li>
- * <li>Consumers may be able to batch data as they consume it leading to more efficient consumption over
- * individual data item consumption where latency associated with the consume operation can be ammortized.
- * For example, it may be possibly to ammortize the cost of a disk seek over many producers.</li>
- * <li>Data from seperate threads can be combined together in the buffer, providing a convenient way of spreading work
- * amongst many workers and gathering the results together again.</li>
- * <li>Different types of queue can be used to hold the buffer, resulting in different processing orders. For example,
- * lifo, fifo, priority heap, etc.</li>
- * </ul>
- *
- * <p/>The asynchronous type of producer/consumer buffers is already well supported by the java.util.concurrent package
- * (in Java 5) and there is also a synchronous queue implementation available there too. This interface extends the
- * blocking queue with some more methods for controlling a synchronous blocking queue. In particular it adds additional
- * take methods that can be used to take data from a queue without releasing producers, so that consumers have an
- * opportunity to confirm correct processing of the data before producers are released. It also adds a put method with
- * exceptions so that consumers can signal exception cases back to producers where there are errors in the data.
- *
- * <p/>This type of queue is usefull in situations where consumers can obtain an efficiency gain by batching data
- * from many threads but where synchronous handling of that data is neccessary because producers need to know that
- * their data has been processed before they continue. For example, sending a bundle of messages together, or writing
- * many records to disk at once, may result in improved performance but the originators of the messages or disk records
- * need confirmation that their data has really been sent or saved to disk.
- *
- * <p/>The consumer can put an element back onto the queue or send an error message to the elements producer using the
- * {@link SynchRecord} interface.
- *
- * <p/>The {@link #take()}, {@link #drainTo(java.util.Collection<? super E>)} and
- * {@link #drainTo(java.util.Collection<? super E>, int)} methods from {@link BlockingQueue} should behave as if they
- * have been called with unblock set to false. That is they take elements from the queue but leave the producers
- * blocked. These methods do not return collections of {@link SynchRecord}s so they do not supply an interface through
- * which errors or re-queuings can be applied. If these methods are used then the consumer must succesfully process
- * all the records it takes.
- *
- * <p/>The {@link #put} method should silently swallow any exceptions that consumers attempt to return to the caller.
- * In order to handle exceptions the {@link #tryPut} method must be used.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Handle synchronous puts, with possible exceptions.
- * <tr><td> Allow consumers to take many records from a queue in a batch.
- * <tr><td> Allow consumers to decide when to unblock synchronous producers.
- * </table>
- */
-public interface BatchSynchQueue<E> extends BlockingQueue<E>
-{
- /**
- * Tries a synchronous put into the queue. If a consumer encounters an exception condition whilst processing the
- * data that is put, then this is returned to the caller wrapped inside a {@link SynchException}.
- *
- * @param e The data element to put into the queue.
- *
- * @throws InterruptedException If the thread is interrupted whilst waiting to write to the queue or whilst waiting
- * on its entry in the queue being consumed.
- * @throws SynchException If a consumer encounters an error whilst processing the data element.
- */
- public void tryPut(E e) throws InterruptedException, SynchException;
-
- /**
- * Takes all available data items from the queue or blocks until some become available. The returned items
- * are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
- * producers, where the producers are still blocked.
- *
- * @param c The collection to drain the data items into.
- * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
- *
- * @return A count of the number of elements that were drained from the queue.
- */
- public SynchRef drainTo(Collection<SynchRecord<E>> c, boolean unblock);
-
- /**
- * Takes up to maxElements available data items from the queue or blocks until some become available. The returned
- * items are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
- * producers, where the producers are still blocked.
- *
- * @param c The collection to drain the data items into.
- * @param maxElements The maximum number of elements to drain.
- * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
- *
- * @return A count of the number of elements that were drained from the queue.
- */
- public SynchRef drainTo(Collection<SynchRecord<E>> c, int maxElements, boolean unblock);
-}
+package org.apache.qpid.util.concurrent;
+
+import java.util.Collection;
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * BatchSynchQueue is an abstraction of the classic producer/consumer buffer pattern for thread interaction. In this
+ * pattern threads can deposit data onto a buffer whilst other threads take data from the buffer and perform usefull
+ * work with it. A BatchSynchQueue adds to this the possibility that producers can be blocked until their data is
+ * consumed or until a consumer chooses to release the producer some time after consuming the data from the queue.
+ *
+ * <p>There are a number of possible advantages to using this technique when compared with having the producers
+ * processing their own data:
+ *
+ * <ul>
+ * <li>Data may be deposited asynchronously in the buffer allowing the producers to continue running.</li>
+ * <li>Data may be deposited synchronously in the buffer so that producers wait until their data has been processed
+ * before being allowed to continue.</li>
+ * <li>Variable rates of production/consumption can be smoothed over by the buffer as it provides space in memory to
+ * hold data between production and consumption.</li>
+ * <li>Consumers may be able to batch data as they consume it leading to more efficient consumption over
+ * individual data item consumption where latency associated with the consume operation can be ammortized.
+ * For example, it may be possibly to ammortize the cost of a disk seek over many producers.</li>
+ * <li>Data from seperate threads can be combined together in the buffer, providing a convenient way of spreading work
+ * amongst many workers and gathering the results together again.</li>
+ * <li>Different types of queue can be used to hold the buffer, resulting in different processing orders. For example,
+ * lifo, fifo, priority heap, etc.</li>
+ * </ul>
+ *
+ * <p/>The asynchronous type of producer/consumer buffers is already well supported by the java.util.concurrent package
+ * (in Java 5) and there is also a synchronous queue implementation available there too. This interface extends the
+ * blocking queue with some more methods for controlling a synchronous blocking queue. In particular it adds additional
+ * take methods that can be used to take data from a queue without releasing producers, so that consumers have an
+ * opportunity to confirm correct processing of the data before producers are released. It also adds a put method with
+ * exceptions so that consumers can signal exception cases back to producers where there are errors in the data.
+ *
+ * <p/>This type of queue is usefull in situations where consumers can obtain an efficiency gain by batching data
+ * from many threads but where synchronous handling of that data is neccessary because producers need to know that
+ * their data has been processed before they continue. For example, sending a bundle of messages together, or writing
+ * many records to disk at once, may result in improved performance but the originators of the messages or disk records
+ * need confirmation that their data has really been sent or saved to disk.
+ *
+ * <p/>The consumer can put an element back onto the queue or send an error message to the elements producer using the
+ * {@link SynchRecord} interface.
+ *
+ * <p/>The {@link #take()}, {@link #drainTo(java.util.Collection<? super E>)} and
+ * {@link #drainTo(java.util.Collection<? super E>, int)} methods from {@link BlockingQueue} should behave as if they
+ * have been called with unblock set to false. That is they take elements from the queue but leave the producers
+ * blocked. These methods do not return collections of {@link SynchRecord}s so they do not supply an interface through
+ * which errors or re-queuings can be applied. If these methods are used then the consumer must succesfully process
+ * all the records it takes.
+ *
+ * <p/>The {@link #put} method should silently swallow any exceptions that consumers attempt to return to the caller.
+ * In order to handle exceptions the {@link #tryPut} method must be used.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Handle synchronous puts, with possible exceptions.
+ * <tr><td> Allow consumers to take many records from a queue in a batch.
+ * <tr><td> Allow consumers to decide when to unblock synchronous producers.
+ * </table>
+ */
+public interface BatchSynchQueue<E> extends BlockingQueue<E>
+{
+ /**
+ * Tries a synchronous put into the queue. If a consumer encounters an exception condition whilst processing the
+ * data that is put, then this is returned to the caller wrapped inside a {@link SynchException}.
+ *
+ * @param e The data element to put into the queue.
+ *
+ * @throws InterruptedException If the thread is interrupted whilst waiting to write to the queue or whilst waiting
+ * on its entry in the queue being consumed.
+ * @throws SynchException If a consumer encounters an error whilst processing the data element.
+ */
+ public void tryPut(E e) throws InterruptedException, SynchException;
+
+ /**
+ * Takes all available data items from the queue or blocks until some become available. The returned items
+ * are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
+ * producers, where the producers are still blocked.
+ *
+ * @param c The collection to drain the data items into.
+ * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
+ *
+ * @return A count of the number of elements that were drained from the queue.
+ */
+ public SynchRef drainTo(Collection<SynchRecord<E>> c, boolean unblock);
+
+ /**
+ * Takes up to maxElements available data items from the queue or blocks until some become available. The returned
+ * items are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
+ * producers, where the producers are still blocked.
+ *
+ * @param c The collection to drain the data items into.
+ * @param maxElements The maximum number of elements to drain.
+ * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
+ *
+ * @return A count of the number of elements that were drained from the queue.
+ */
+ public SynchRef drainTo(Collection<SynchRecord<E>> c, int maxElements, boolean unblock);
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueueBase.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueueBase.java
index 47eff4be19..d1c1abd285 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueueBase.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BatchSynchQueueBase.java
@@ -1,813 +1,813 @@
-package org.apache.qpid.util.concurrent;
-
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * Synchronous/Asynchronous puts. Asynchronous is easiest, just wait till can write to queue and deposit data.
- * Synchronous is harder. Deposit data, but then must wait until deposited element/elements are taken before being
- * allowed to unblock and continue. Consumer needs some options here too. Can just get the data from the buffer and
- * allow any producers unblocked as a result to continue, or can get data but continue blocking while the data is
- * processed before sending a message to do the unblocking. Synch/Asynch mode to be controlled by a switch.
- * Unblocking/not unblocking during consumer processing to be controlled by the consumers calls.
- *
- * <p/>Implementing sub-classes only need to supply an implementation of a queue to produce a valid concrete
- * implementation of this. This queue is only accessed through the methods {@link #insert}, {@link #extract},
- * {@link #getBufferCapacity()}, {@link #peekAtBufferHead()}. An implementation can override these methods to implement
- * the buffer other than by a queue, for example, by using an array.
- *
- * <p/>Normal queue methods to work asynchronously.
- * <p/>Put, take and drain methods from the BlockingQueue interface work synchronously but unblock producers immediately
- * when their data is taken.
- * <p/>The additional put, take and drain methods from the BatchSynchQueue interface work synchronously and provide the
- * option to keep producers blocked until the consumer decides to release them.
- *
- * <p/>Removed take method that keeps producers blocked as it is pointless. Essentially it reduces this class to
- * synchronous processing of individual data items, which negates the point of the hand-off design. The efficiency
- * gain of the hand off design comes in being able to batch consume requests, ammortizing latency (such as caused by io)
- * accross many producers. The only advantage of the single blocking take method is that it did take advantage of the
- * queue ordering, which ma be usefull, for example to apply a priority ordering amongst producers. This is also an
- * advantage over the java.util.concurrent.SynchronousQueue which doesn't have a backing queue which can be used to
- * apply orderings. If a single item take is really needed can just use the drainTo method with a maximum of one item.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-public abstract class BatchSynchQueueBase<E> extends AbstractQueue<E> implements BatchSynchQueue<E>
-{
- /** Used for logging. */
- private static final Logger log = LoggerFactory.getLogger(BatchSynchQueueBase.class);
-
- /** Holds a reference to the queue implementation that holds the buffer. */
- Queue<SynchRecordImpl<E>> buffer;
-
- /** Holds the number of items in the queue */
- private int count;
-
- /** Main lock guarding all access */
- private ReentrantLock lock;
-
- /** Condition for waiting takes */
- private Condition notEmpty;
-
- /** Condition for waiting puts */
- private Condition notFull;
-
- /**
- * Creates a batch synch queue without fair thread scheduling.
- */
- public BatchSynchQueueBase()
- {
- this(false);
- }
-
- /**
- * Ensures that the underlying buffer implementation is created.
- *
- * @param fair <tt>true</tt> if fairness is to be applied to threads waiting to access the buffer.
- */
- public BatchSynchQueueBase(boolean fair)
- {
- buffer = this.createQueue();
-
- // Create the buffer lock with the fairness flag set accordingly.
- lock = new ReentrantLock(fair);
-
- // Create the non-empty and non-full condition monitors on the buffer lock.
- notEmpty = lock.newCondition();
- notFull = lock.newCondition();
- }
-
- /**
- * Returns an iterator over the elements contained in this collection.
- *
- * @return An iterator over the elements contained in this collection.
- */
- public Iterator<E> iterator()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Returns the number of elements in this collection. If the collection contains more than
- * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>.
- *
- * @return The number of elements in this collection.
- */
- public int size()
- {
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- return count;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Inserts the specified element into this queue, if possible. When using queues that may impose insertion
- * restrictions (for example capacity bounds), method <tt>offer</tt> is generally preferable to method
- * {@link java.util.Collection#add}, which can fail to insert an element only by throwing an exception.
- *
- * @param e The element to insert.
- *
- * @return <tt>true</tt> if it was possible to add the element to this queue, else <tt>false</tt>
- */
- public boolean offer(E e)
- {
- if (e == null)
- {
- throw new NullPointerException();
- }
-
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- return insert(e, false);
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Inserts the specified element into this queue, waiting if necessary up to the specified wait time for space to
- * become available.
- *
- * @param e The element to add.
- * @param timeout How long to wait before giving up, in units of <tt>unit</tt>
- * @param unit A <tt>TimeUnit</tt> determining how to interpret the <tt>timeout</tt> parameter.
- *
- * @return <tt>true</tt> if successful, or <tt>false</tt> if the specified waiting time elapses before space is
- * available.
- *
- * @throws InterruptedException If interrupted while waiting.
- * @throws NullPointerException If the specified element is <tt>null</tt>.
- */
- public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException
- {
- if (e == null)
- {
- throw new NullPointerException();
- }
-
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
-
- long nanos = unit.toNanos(timeout);
-
- try
- {
- do
- {
- if (insert(e, false))
- {
- return true;
- }
-
- try
- {
- nanos = notFull.awaitNanos(nanos);
- }
- catch (InterruptedException ie)
- {
- notFull.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- }
- while (nanos > 0);
-
- return false;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Retrieves and removes the head of this queue, or <tt>null</tt> if this queue is empty.
- *
- * @return The head of this queue, or <tt>null</tt> if this queue is empty.
- */
- public E poll()
- {
- final ReentrantLock lock = this.lock;
-
- lock.lock();
- try
- {
- if (count == 0)
- {
- return null;
- }
-
- E x = extract(true, true).getElement();
-
- return x;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Retrieves and removes the head of this queue, waiting if necessary up to the specified wait time if no elements
- * are present on this queue.
- *
- * @param timeout How long to wait before giving up, in units of <tt>unit</tt>.
- * @param unit A <tt>TimeUnit</tt> determining how to interpret the <tt>timeout</tt> parameter.
- *
- * @return The head of this queue, or <tt>null</tt> if the specified waiting time elapses before an element is present.
- *
- * @throws InterruptedException If interrupted while waiting.
- */
- public E poll(long timeout, TimeUnit unit) throws InterruptedException
- {
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
- try
- {
- long nanos = unit.toNanos(timeout);
-
- do
- {
- if (count != 0)
- {
- E x = extract(true, true).getElement();
-
- return x;
- }
-
- try
- {
- nanos = notEmpty.awaitNanos(nanos);
- }
- catch (InterruptedException ie)
- {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- }
- while (nanos > 0);
-
- return null;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Retrieves, but does not remove, the head of this queue, returning <tt>null</tt> if this queue is empty.
- *
- * @return The head of this queue, or <tt>null</tt> if this queue is empty.
- */
- public E peek()
- {
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- return peekAtBufferHead();
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Returns the number of elements that this queue can ideally (in the absence of memory or resource constraints)
- * accept without blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic limit.
- *
- * <p>Note that you <em>cannot</em> always tell if an attempt to <tt>add</tt> an element will succeed by
- * inspecting <tt>remainingCapacity</tt> because it may be the case that another thread is about to <tt>put</tt>
- * or <tt>take</tt> an element.
- *
- * @return The remaining capacity.
- */
- public int remainingCapacity()
- {
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- return getBufferCapacity() - count;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Adds the specified element to this queue, waiting if necessary for space to become available.
- *
- * <p/>This method delegated to {@link #tryPut} which can raise {@link SynchException}s. If any are raised
- * this method silently ignores them. Use the {@link #tryPut} method directly if you want to catch these
- * exceptions.
- *
- * @param e The element to add.
- *
- * @throws InterruptedException If interrupted while waiting.
- */
- public void put(E e) throws InterruptedException
- {
- try
- {
- tryPut(e);
- }
- catch (SynchException ex)
- {
- // This exception is deliberately ignored. See the method comment for information about this.
- }
- }
-
- /**
- * Tries a synchronous put into the queue. If a consumer encounters an exception condition whilst processing the
- * data that is put, then this is returned to the caller wrapped inside a {@link SynchException}.
- *
- * @param e The data element to put into the queue. Cannot be null.
- *
- * @throws InterruptedException If the thread is interrupted whilst waiting to write to the queue or whilst waiting
- * on its entry in the queue being consumed.
- * @throws SynchException If a consumer encounters an error whilst processing the data element.
- */
- public void tryPut(E e) throws InterruptedException, SynchException
- {
- if (e == null)
- {
- throw new NullPointerException();
- }
-
- // final Queue<E> items = this.buffer;
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
-
- try
- {
- while (count == getBufferCapacity())
- {
- // Release the lock and wait until the queue is not full.
- notFull.await();
- }
- }
- catch (InterruptedException ie)
- {
- notFull.signal(); // propagate to non-interrupted thread
- throw ie;
- }
-
- // There is room in the queue so insert must succeed. Insert into the queu, release the lock and block
- // the producer until its data is taken.
- insert(e, true);
- }
-
- /**
- * Retrieves and removes the head of this queue, waiting if no elements are present on this queue.
- * Any producer that has its data element taken by this call will be immediately unblocked. To keep the
- * producer blocked whilst taking just a single item, use the
- * {@link #drainTo(java.util.Collection<org.apache.qpid.util.concurrent.SynchRecord<E>>, int, boolean)}
- * method. There is no take method to do that because there is not usually any advantage in a synchronous hand
- * off design that consumes data one item at a time. It is normal to consume data in chunks to ammortize consumption
- * latencies accross many producers where possible.
- *
- * @return The head of this queue.
- *
- * @throws InterruptedException if interrupted while waiting.
- */
- public E take() throws InterruptedException
- {
- final ReentrantLock lock = this.lock;
- lock.lockInterruptibly();
-
- try
- {
- try
- {
- while (count == 0)
- {
- // Release the lock and wait until the queue becomes non-empty.
- notEmpty.await();
- }
- }
- catch (InterruptedException ie)
- {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
-
- // There is data in the queue so extraction must succeed. Notify any waiting threads that the queue is
- // not full, and unblock the producer that owns the data item that is taken.
- E x = extract(true, true).getElement();
-
- return x;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Removes all available elements from this queue and adds them into the given collection. This operation may be
- * more efficient than repeatedly polling this queue. A failure encountered while attempting to <tt>add</tt> elements
- * to collection <tt>c</tt> may result in elements being in neither, either or both collections when the associated
- * exception is thrown. Attempts to drain a queue to itself result in <tt>IllegalArgumentException</tt>. Further,
- * the behavior of this operation is undefined if the specified collection is modified while the operation is in
- * progress.
- *
- * @param objects The collection to transfer elements into.
- *
- * @return The number of elements transferred.
- *
- * @throws NullPointerException If objects is null.
- * @throws IllegalArgumentException If objects is this queue.
- */
- public int drainTo(Collection<? super E> objects)
- {
- return drainTo(objects, -1);
- }
-
- /**
- * Removes at most the given number of available elements from this queue and adds them into the given collection.
- * A failure encountered while attempting to <tt>add</tt> elements to collection <tt>c</tt> may result in elements
- * being in neither, either or both collections when the associated exception is thrown. Attempts to drain a queue
- * to itself result in <tt>IllegalArgumentException</tt>. Further, the behavior of this operation is undefined if
- * the specified collection is modified while the operation is in progress.
- *
- * @param objects The collection to transfer elements into.
- * @param maxElements The maximum number of elements to transfer. If this is -1 then that is interpreted as meaning
- * all elements.
- *
- * @return The number of elements transferred.
- *
- * @throws NullPointerException If c is null.
- * @throws IllegalArgumentException If c is this queue.
- */
- public int drainTo(Collection<? super E> objects, int maxElements)
- {
- if (objects == null)
- {
- throw new NullPointerException();
- }
-
- if (objects == this)
- {
- throw new IllegalArgumentException();
- }
-
- // final Queue<E> items = this.buffer;
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- int n = 0;
-
- for (int max = ((maxElements >= count) || (maxElements < 0)) ? count : maxElements; n < max; n++)
- {
- // Take items from the queue, do unblock the producers, but don't send not full signals yet.
- objects.add(extract(true, false).getElement());
- }
-
- if (n > 0)
- {
- // count -= n;
- notFull.signalAll();
- }
-
- return n;
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * Takes all available data items from the queue or blocks until some become available. The returned items
- * are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
- * producers, where the producers are still blocked.
- *
- * @param c The collection to drain the data items into.
- * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
- *
- * @return A count of the number of elements that were drained from the queue.
- */
- public SynchRef drainTo(Collection<SynchRecord<E>> c, boolean unblock)
- {
- return drainTo(c, -1, unblock);
- }
-
- /**
- * Takes up to maxElements available data items from the queue or blocks until some become available. The returned
- * items are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
- * producers, where the producers are still blocked.
- *
- * @param coll The collection to drain the data items into.
- * @param maxElements The maximum number of elements to drain.
- * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
- *
- * @return A count of the number of elements that were drained from the queue.
- */
- public SynchRef drainTo(Collection<SynchRecord<E>> coll, int maxElements, boolean unblock)
- {
- if (coll == null)
- {
- throw new NullPointerException();
- }
-
- // final Queue<E> items = this.buffer;
- final ReentrantLock lock = this.lock;
- lock.lock();
-
- try
- {
- int n = 0;
-
- for (int max = ((maxElements >= count) || (maxElements < 0)) ? count : maxElements; n < max; n++)
- {
- // Extract the next record from the queue, don't signall the not full condition yet and release
- // producers depending on whether the caller wants to or not.
- coll.add(extract(false, unblock));
- }
-
- if (n > 0)
- {
- // count -= n;
- notFull.signalAll();
- }
-
- return new SynchRefImpl(n, coll);
- }
- finally
- {
- lock.unlock();
- }
- }
-
- /**
- * This abstract method should be overriden to return an empty queue. Different implementations of producer
- * consumer buffers can control the order in which data is accessed using different queue implementations.
- * This method allows the type of queue to be abstracted out of this class and to be supplied by concrete
- * implementations.
- *
- * @return An empty queue.
- */
- protected abstract <T> Queue<T> createQueue();
-
- /**
- * Insert element into the queue, then possibly signal that the queue is not empty and block the producer
- * on the element until permission to procede is given.
- *
- * <p/>If the producer is to be blocked then the lock must be released first, otherwise no other process
- * will be able to get access to the queue. Hence, unlock and block are always set together.
- *
- * <p/>Call only when holding the global lock.
- *
- * @param unlockAndBlock <tt>true</tt>If the global queue lock should be released and the producer should be blocked.
- *
- * @return <tt>true</tt> if the operation succeeded, <tt>false</tt> otherwise. If the result is <tt>true</tt> this
- * method may not return straight away, but only after the producer is unblocked by having its data
- * consumed if the unlockAndBlock flag is set. In the false case the method will return straight away, no
- * matter what value the unlockAndBlock flag has, leaving the global lock on.
- */
- protected boolean insert(E x, boolean unlockAndBlock)
- {
- // Create a new record for the data item.
- SynchRecordImpl<E> record = new SynchRecordImpl<E>(x);
-
- boolean result = buffer.offer(record);
-
- if (result)
- {
- count++;
-
- // Tell any waiting consumers that the queue is not empty.
- notEmpty.signal();
-
- if (unlockAndBlock)
- {
- // Allow other threads to read/write the queue.
- lock.unlock();
-
- // Wait until a consumer takes this data item.
- record.waitForConsumer();
- }
-
- return true;
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Extract element at current take position, advance, and signal.
- *
- * <p/>Call only when holding lock.
- */
- protected SynchRecordImpl<E> extract(boolean unblock, boolean signal)
- {
- SynchRecordImpl<E> result = buffer.remove();
- count--;
-
- if (signal)
- {
- notFull.signal();
- }
-
- if (unblock)
- {
- result.releaseImmediately();
- }
-
- return result;
- }
-
- /**
- * Get the capacity of the buffer. If the buffer has no maximum capacity then Integer.MAX_VALUE is returned.
- *
- * <p/>Call only when holding lock.
- *
- * @return The maximum capacity of the buffer.
- */
- protected int getBufferCapacity()
- {
- if (buffer instanceof Capacity)
- {
- return ((Capacity) buffer).getCapacity();
- }
- else
- {
- return Integer.MAX_VALUE;
- }
- }
-
- /**
- * Return the head element from the buffer.
- *
- * <p/>Call only when holding lock.
- *
- * @return The head element from the buffer.
- */
- protected E peekAtBufferHead()
- {
- return buffer.peek().getElement();
- }
-
- public class SynchRefImpl implements SynchRef
- {
- /** Holds the number of synch records associated with this reference. */
- int numRecords;
-
- /** Holds a reference to the collection of synch records managed by this. */
- Collection<SynchRecord<E>> records;
-
- public SynchRefImpl(int n, Collection<SynchRecord<E>> records)
- {
- this.numRecords = n;
- this.records = records;
- }
-
- public int getNumRecords()
- {
- return numRecords;
- }
-
- /**
- * Any producers that have had their data elements taken from the queue but have not been unblocked are unblocked
- * when this method is called. The exception to this is producers that have had their data put back onto the queue
- * by a consumer. Producers that have had exceptions for their data items registered by consumers will be unblocked
- * but will not return from their put call normally, but with an exception instead.
- */
- public void unblockProducers()
- {
- log.debug("public void unblockProducers(): called");
-
- if (records != null)
- {
- for (SynchRecord<E> record : records)
- {
- // This call takes account of items that have already been released, are to be requeued or are in
- // error.
- record.releaseImmediately();
- }
- }
-
- records = null;
- }
- }
-
- /**
- * A SynchRecordImpl is used by a {@link BatchSynchQueue} to pair together a producer with its data. This allows
- * the producer of data to be identified so that it can be unblocked when its data is consumed or sent errors when
- * its data cannot be consumed.
- */
- public class SynchRecordImpl<E> implements SynchRecord<E>
- {
- /** A boolean latch that determines when the producer for this data item will be allowed to continue. */
- BooleanLatch latch = new BooleanLatch();
-
- /** The data element associated with this item. */
- E element;
-
- /**
- * Create a new synch record.
- *
- * @param e The data element that the record encapsulates.
- */
- public SynchRecordImpl(E e)
- {
- // Keep the data element.
- element = e;
- }
-
- /**
- * Waits until the producer is given permission to proceded by a consumer.
- */
- public void waitForConsumer()
- {
- latch.await();
- }
-
- /**
- * Gets the data element contained by this record.
- *
- * @return The data element contained by this record.
- */
- public E getElement()
- {
- return element;
- }
-
- /**
- * Immediately releases the producer of this data record. Consumers can bring the synchronization time of
- * producers to a minimum by using this method to release them at the earliest possible moment when batch
- * consuming records from sychronized producers.
- */
- public void releaseImmediately()
- {
- // Check that the record has not already been released, is in error or is to be requeued.
- latch.signal();
-
- // Propagate errors to the producer.
-
- // Requeue items to be requeued.
- }
-
- /**
- * Tells the synch queue to put this element back onto the queue instead of releasing its producer.
- * The element is not requeued immediately but upon calling the {@link SynchRef#unblockProducers()} method or
- * the {@link #releaseImmediately()} method.
- *
- * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this
- * element has already been unblocked.
- */
- public void reQueue()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Tells the synch queue to raise an exception with this elements producer. The exception is not raised
- * immediately but upon calling the {@link SynchRef#unblockProducers()} method or the
- * {@link #releaseImmediately()} method. The exception will be wrapped in a {@link SynchException} before it is
- * raised on the producer.
- *
- * <p/>This method is unusual in that it accepts an exception as an argument. This is non-standard but is used
- * because the exception is to be passed onto a different thread.
- *
- * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this
- * element has already been unblocked.
- *
- * @param e The exception to raise on the producer.
- */
- public void inError(Exception e)
- {
- throw new RuntimeException("Not implemented.");
- }
- }
-}
+package org.apache.qpid.util.concurrent;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Synchronous/Asynchronous puts. Asynchronous is easiest, just wait till can write to queue and deposit data.
+ * Synchronous is harder. Deposit data, but then must wait until deposited element/elements are taken before being
+ * allowed to unblock and continue. Consumer needs some options here too. Can just get the data from the buffer and
+ * allow any producers unblocked as a result to continue, or can get data but continue blocking while the data is
+ * processed before sending a message to do the unblocking. Synch/Asynch mode to be controlled by a switch.
+ * Unblocking/not unblocking during consumer processing to be controlled by the consumers calls.
+ *
+ * <p/>Implementing sub-classes only need to supply an implementation of a queue to produce a valid concrete
+ * implementation of this. This queue is only accessed through the methods {@link #insert}, {@link #extract},
+ * {@link #getBufferCapacity()}, {@link #peekAtBufferHead()}. An implementation can override these methods to implement
+ * the buffer other than by a queue, for example, by using an array.
+ *
+ * <p/>Normal queue methods to work asynchronously.
+ * <p/>Put, take and drain methods from the BlockingQueue interface work synchronously but unblock producers immediately
+ * when their data is taken.
+ * <p/>The additional put, take and drain methods from the BatchSynchQueue interface work synchronously and provide the
+ * option to keep producers blocked until the consumer decides to release them.
+ *
+ * <p/>Removed take method that keeps producers blocked as it is pointless. Essentially it reduces this class to
+ * synchronous processing of individual data items, which negates the point of the hand-off design. The efficiency
+ * gain of the hand off design comes in being able to batch consume requests, ammortizing latency (such as caused by io)
+ * accross many producers. The only advantage of the single blocking take method is that it did take advantage of the
+ * queue ordering, which ma be usefull, for example to apply a priority ordering amongst producers. This is also an
+ * advantage over the java.util.concurrent.SynchronousQueue which doesn't have a backing queue which can be used to
+ * apply orderings. If a single item take is really needed can just use the drainTo method with a maximum of one item.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ */
+public abstract class BatchSynchQueueBase<E> extends AbstractQueue<E> implements BatchSynchQueue<E>
+{
+ /** Used for logging. */
+ private static final Logger log = LoggerFactory.getLogger(BatchSynchQueueBase.class);
+
+ /** Holds a reference to the queue implementation that holds the buffer. */
+ Queue<SynchRecordImpl<E>> buffer;
+
+ /** Holds the number of items in the queue */
+ private int count;
+
+ /** Main lock guarding all access */
+ private ReentrantLock lock;
+
+ /** Condition for waiting takes */
+ private Condition notEmpty;
+
+ /** Condition for waiting puts */
+ private Condition notFull;
+
+ /**
+ * Creates a batch synch queue without fair thread scheduling.
+ */
+ public BatchSynchQueueBase()
+ {
+ this(false);
+ }
+
+ /**
+ * Ensures that the underlying buffer implementation is created.
+ *
+ * @param fair <tt>true</tt> if fairness is to be applied to threads waiting to access the buffer.
+ */
+ public BatchSynchQueueBase(boolean fair)
+ {
+ buffer = this.createQueue();
+
+ // Create the buffer lock with the fairness flag set accordingly.
+ lock = new ReentrantLock(fair);
+
+ // Create the non-empty and non-full condition monitors on the buffer lock.
+ notEmpty = lock.newCondition();
+ notFull = lock.newCondition();
+ }
+
+ /**
+ * Returns an iterator over the elements contained in this collection.
+ *
+ * @return An iterator over the elements contained in this collection.
+ */
+ public Iterator<E> iterator()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Returns the number of elements in this collection. If the collection contains more than
+ * <tt>Integer.MAX_VALUE</tt> elements, returns <tt>Integer.MAX_VALUE</tt>.
+ *
+ * @return The number of elements in this collection.
+ */
+ public int size()
+ {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ return count;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this queue, if possible. When using queues that may impose insertion
+ * restrictions (for example capacity bounds), method <tt>offer</tt> is generally preferable to method
+ * {@link java.util.Collection#add}, which can fail to insert an element only by throwing an exception.
+ *
+ * @param e The element to insert.
+ *
+ * @return <tt>true</tt> if it was possible to add the element to this queue, else <tt>false</tt>
+ */
+ public boolean offer(E e)
+ {
+ if (e == null)
+ {
+ throw new NullPointerException();
+ }
+
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ return insert(e, false);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Inserts the specified element into this queue, waiting if necessary up to the specified wait time for space to
+ * become available.
+ *
+ * @param e The element to add.
+ * @param timeout How long to wait before giving up, in units of <tt>unit</tt>
+ * @param unit A <tt>TimeUnit</tt> determining how to interpret the <tt>timeout</tt> parameter.
+ *
+ * @return <tt>true</tt> if successful, or <tt>false</tt> if the specified waiting time elapses before space is
+ * available.
+ *
+ * @throws InterruptedException If interrupted while waiting.
+ * @throws NullPointerException If the specified element is <tt>null</tt>.
+ */
+ public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException
+ {
+ if (e == null)
+ {
+ throw new NullPointerException();
+ }
+
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+
+ long nanos = unit.toNanos(timeout);
+
+ try
+ {
+ do
+ {
+ if (insert(e, false))
+ {
+ return true;
+ }
+
+ try
+ {
+ nanos = notFull.awaitNanos(nanos);
+ }
+ catch (InterruptedException ie)
+ {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ while (nanos > 0);
+
+ return false;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, or <tt>null</tt> if this queue is empty.
+ *
+ * @return The head of this queue, or <tt>null</tt> if this queue is empty.
+ */
+ public E poll()
+ {
+ final ReentrantLock lock = this.lock;
+
+ lock.lock();
+ try
+ {
+ if (count == 0)
+ {
+ return null;
+ }
+
+ E x = extract(true, true).getElement();
+
+ return x;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if necessary up to the specified wait time if no elements
+ * are present on this queue.
+ *
+ * @param timeout How long to wait before giving up, in units of <tt>unit</tt>.
+ * @param unit A <tt>TimeUnit</tt> determining how to interpret the <tt>timeout</tt> parameter.
+ *
+ * @return The head of this queue, or <tt>null</tt> if the specified waiting time elapses before an element is present.
+ *
+ * @throws InterruptedException If interrupted while waiting.
+ */
+ public E poll(long timeout, TimeUnit unit) throws InterruptedException
+ {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+ try
+ {
+ long nanos = unit.toNanos(timeout);
+
+ do
+ {
+ if (count != 0)
+ {
+ E x = extract(true, true).getElement();
+
+ return x;
+ }
+
+ try
+ {
+ nanos = notEmpty.awaitNanos(nanos);
+ }
+ catch (InterruptedException ie)
+ {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+ }
+ while (nanos > 0);
+
+ return null;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, returning <tt>null</tt> if this queue is empty.
+ *
+ * @return The head of this queue, or <tt>null</tt> if this queue is empty.
+ */
+ public E peek()
+ {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ return peekAtBufferHead();
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Returns the number of elements that this queue can ideally (in the absence of memory or resource constraints)
+ * accept without blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic limit.
+ *
+ * <p>Note that you <em>cannot</em> always tell if an attempt to <tt>add</tt> an element will succeed by
+ * inspecting <tt>remainingCapacity</tt> because it may be the case that another thread is about to <tt>put</tt>
+ * or <tt>take</tt> an element.
+ *
+ * @return The remaining capacity.
+ */
+ public int remainingCapacity()
+ {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ return getBufferCapacity() - count;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Adds the specified element to this queue, waiting if necessary for space to become available.
+ *
+ * <p/>This method delegated to {@link #tryPut} which can raise {@link SynchException}s. If any are raised
+ * this method silently ignores them. Use the {@link #tryPut} method directly if you want to catch these
+ * exceptions.
+ *
+ * @param e The element to add.
+ *
+ * @throws InterruptedException If interrupted while waiting.
+ */
+ public void put(E e) throws InterruptedException
+ {
+ try
+ {
+ tryPut(e);
+ }
+ catch (SynchException ex)
+ {
+ // This exception is deliberately ignored. See the method comment for information about this.
+ }
+ }
+
+ /**
+ * Tries a synchronous put into the queue. If a consumer encounters an exception condition whilst processing the
+ * data that is put, then this is returned to the caller wrapped inside a {@link SynchException}.
+ *
+ * @param e The data element to put into the queue. Cannot be null.
+ *
+ * @throws InterruptedException If the thread is interrupted whilst waiting to write to the queue or whilst waiting
+ * on its entry in the queue being consumed.
+ * @throws SynchException If a consumer encounters an error whilst processing the data element.
+ */
+ public void tryPut(E e) throws InterruptedException, SynchException
+ {
+ if (e == null)
+ {
+ throw new NullPointerException();
+ }
+
+ // final Queue<E> items = this.buffer;
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+
+ try
+ {
+ while (count == getBufferCapacity())
+ {
+ // Release the lock and wait until the queue is not full.
+ notFull.await();
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ notFull.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+
+ // There is room in the queue so insert must succeed. Insert into the queu, release the lock and block
+ // the producer until its data is taken.
+ insert(e, true);
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, waiting if no elements are present on this queue.
+ * Any producer that has its data element taken by this call will be immediately unblocked. To keep the
+ * producer blocked whilst taking just a single item, use the
+ * {@link #drainTo(java.util.Collection<org.apache.qpid.util.concurrent.SynchRecord<E>>, int, boolean)}
+ * method. There is no take method to do that because there is not usually any advantage in a synchronous hand
+ * off design that consumes data one item at a time. It is normal to consume data in chunks to ammortize consumption
+ * latencies accross many producers where possible.
+ *
+ * @return The head of this queue.
+ *
+ * @throws InterruptedException if interrupted while waiting.
+ */
+ public E take() throws InterruptedException
+ {
+ final ReentrantLock lock = this.lock;
+ lock.lockInterruptibly();
+
+ try
+ {
+ try
+ {
+ while (count == 0)
+ {
+ // Release the lock and wait until the queue becomes non-empty.
+ notEmpty.await();
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ notEmpty.signal(); // propagate to non-interrupted thread
+ throw ie;
+ }
+
+ // There is data in the queue so extraction must succeed. Notify any waiting threads that the queue is
+ // not full, and unblock the producer that owns the data item that is taken.
+ E x = extract(true, true).getElement();
+
+ return x;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Removes all available elements from this queue and adds them into the given collection. This operation may be
+ * more efficient than repeatedly polling this queue. A failure encountered while attempting to <tt>add</tt> elements
+ * to collection <tt>c</tt> may result in elements being in neither, either or both collections when the associated
+ * exception is thrown. Attempts to drain a queue to itself result in <tt>IllegalArgumentException</tt>. Further,
+ * the behavior of this operation is undefined if the specified collection is modified while the operation is in
+ * progress.
+ *
+ * @param objects The collection to transfer elements into.
+ *
+ * @return The number of elements transferred.
+ *
+ * @throws NullPointerException If objects is null.
+ * @throws IllegalArgumentException If objects is this queue.
+ */
+ public int drainTo(Collection<? super E> objects)
+ {
+ return drainTo(objects, -1);
+ }
+
+ /**
+ * Removes at most the given number of available elements from this queue and adds them into the given collection.
+ * A failure encountered while attempting to <tt>add</tt> elements to collection <tt>c</tt> may result in elements
+ * being in neither, either or both collections when the associated exception is thrown. Attempts to drain a queue
+ * to itself result in <tt>IllegalArgumentException</tt>. Further, the behavior of this operation is undefined if
+ * the specified collection is modified while the operation is in progress.
+ *
+ * @param objects The collection to transfer elements into.
+ * @param maxElements The maximum number of elements to transfer. If this is -1 then that is interpreted as meaning
+ * all elements.
+ *
+ * @return The number of elements transferred.
+ *
+ * @throws NullPointerException If c is null.
+ * @throws IllegalArgumentException If c is this queue.
+ */
+ public int drainTo(Collection<? super E> objects, int maxElements)
+ {
+ if (objects == null)
+ {
+ throw new NullPointerException();
+ }
+
+ if (objects == this)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ // final Queue<E> items = this.buffer;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ int n = 0;
+
+ for (int max = ((maxElements >= count) || (maxElements < 0)) ? count : maxElements; n < max; n++)
+ {
+ // Take items from the queue, do unblock the producers, but don't send not full signals yet.
+ objects.add(extract(true, false).getElement());
+ }
+
+ if (n > 0)
+ {
+ // count -= n;
+ notFull.signalAll();
+ }
+
+ return n;
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * Takes all available data items from the queue or blocks until some become available. The returned items
+ * are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
+ * producers, where the producers are still blocked.
+ *
+ * @param c The collection to drain the data items into.
+ * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
+ *
+ * @return A count of the number of elements that were drained from the queue.
+ */
+ public SynchRef drainTo(Collection<SynchRecord<E>> c, boolean unblock)
+ {
+ return drainTo(c, -1, unblock);
+ }
+
+ /**
+ * Takes up to maxElements available data items from the queue or blocks until some become available. The returned
+ * items are wrapped in a {@link SynchRecord} which provides an interface to requeue them or send errors to their
+ * producers, where the producers are still blocked.
+ *
+ * @param coll The collection to drain the data items into.
+ * @param maxElements The maximum number of elements to drain.
+ * @param unblock If set to <tt>true</tt> the producers for the taken items will be immediately unblocked.
+ *
+ * @return A count of the number of elements that were drained from the queue.
+ */
+ public SynchRef drainTo(Collection<SynchRecord<E>> coll, int maxElements, boolean unblock)
+ {
+ if (coll == null)
+ {
+ throw new NullPointerException();
+ }
+
+ // final Queue<E> items = this.buffer;
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+
+ try
+ {
+ int n = 0;
+
+ for (int max = ((maxElements >= count) || (maxElements < 0)) ? count : maxElements; n < max; n++)
+ {
+ // Extract the next record from the queue, don't signall the not full condition yet and release
+ // producers depending on whether the caller wants to or not.
+ coll.add(extract(false, unblock));
+ }
+
+ if (n > 0)
+ {
+ // count -= n;
+ notFull.signalAll();
+ }
+
+ return new SynchRefImpl(n, coll);
+ }
+ finally
+ {
+ lock.unlock();
+ }
+ }
+
+ /**
+ * This abstract method should be overriden to return an empty queue. Different implementations of producer
+ * consumer buffers can control the order in which data is accessed using different queue implementations.
+ * This method allows the type of queue to be abstracted out of this class and to be supplied by concrete
+ * implementations.
+ *
+ * @return An empty queue.
+ */
+ protected abstract <T> Queue<T> createQueue();
+
+ /**
+ * Insert element into the queue, then possibly signal that the queue is not empty and block the producer
+ * on the element until permission to procede is given.
+ *
+ * <p/>If the producer is to be blocked then the lock must be released first, otherwise no other process
+ * will be able to get access to the queue. Hence, unlock and block are always set together.
+ *
+ * <p/>Call only when holding the global lock.
+ *
+ * @param unlockAndBlock <tt>true</tt>If the global queue lock should be released and the producer should be blocked.
+ *
+ * @return <tt>true</tt> if the operation succeeded, <tt>false</tt> otherwise. If the result is <tt>true</tt> this
+ * method may not return straight away, but only after the producer is unblocked by having its data
+ * consumed if the unlockAndBlock flag is set. In the false case the method will return straight away, no
+ * matter what value the unlockAndBlock flag has, leaving the global lock on.
+ */
+ protected boolean insert(E x, boolean unlockAndBlock)
+ {
+ // Create a new record for the data item.
+ SynchRecordImpl<E> record = new SynchRecordImpl<E>(x);
+
+ boolean result = buffer.offer(record);
+
+ if (result)
+ {
+ count++;
+
+ // Tell any waiting consumers that the queue is not empty.
+ notEmpty.signal();
+
+ if (unlockAndBlock)
+ {
+ // Allow other threads to read/write the queue.
+ lock.unlock();
+
+ // Wait until a consumer takes this data item.
+ record.waitForConsumer();
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Extract element at current take position, advance, and signal.
+ *
+ * <p/>Call only when holding lock.
+ */
+ protected SynchRecordImpl<E> extract(boolean unblock, boolean signal)
+ {
+ SynchRecordImpl<E> result = buffer.remove();
+ count--;
+
+ if (signal)
+ {
+ notFull.signal();
+ }
+
+ if (unblock)
+ {
+ result.releaseImmediately();
+ }
+
+ return result;
+ }
+
+ /**
+ * Get the capacity of the buffer. If the buffer has no maximum capacity then Integer.MAX_VALUE is returned.
+ *
+ * <p/>Call only when holding lock.
+ *
+ * @return The maximum capacity of the buffer.
+ */
+ protected int getBufferCapacity()
+ {
+ if (buffer instanceof Capacity)
+ {
+ return ((Capacity) buffer).getCapacity();
+ }
+ else
+ {
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ /**
+ * Return the head element from the buffer.
+ *
+ * <p/>Call only when holding lock.
+ *
+ * @return The head element from the buffer.
+ */
+ protected E peekAtBufferHead()
+ {
+ return buffer.peek().getElement();
+ }
+
+ public class SynchRefImpl implements SynchRef
+ {
+ /** Holds the number of synch records associated with this reference. */
+ int numRecords;
+
+ /** Holds a reference to the collection of synch records managed by this. */
+ Collection<SynchRecord<E>> records;
+
+ public SynchRefImpl(int n, Collection<SynchRecord<E>> records)
+ {
+ this.numRecords = n;
+ this.records = records;
+ }
+
+ public int getNumRecords()
+ {
+ return numRecords;
+ }
+
+ /**
+ * Any producers that have had their data elements taken from the queue but have not been unblocked are unblocked
+ * when this method is called. The exception to this is producers that have had their data put back onto the queue
+ * by a consumer. Producers that have had exceptions for their data items registered by consumers will be unblocked
+ * but will not return from their put call normally, but with an exception instead.
+ */
+ public void unblockProducers()
+ {
+ log.debug("public void unblockProducers(): called");
+
+ if (records != null)
+ {
+ for (SynchRecord<E> record : records)
+ {
+ // This call takes account of items that have already been released, are to be requeued or are in
+ // error.
+ record.releaseImmediately();
+ }
+ }
+
+ records = null;
+ }
+ }
+
+ /**
+ * A SynchRecordImpl is used by a {@link BatchSynchQueue} to pair together a producer with its data. This allows
+ * the producer of data to be identified so that it can be unblocked when its data is consumed or sent errors when
+ * its data cannot be consumed.
+ */
+ public class SynchRecordImpl<E> implements SynchRecord<E>
+ {
+ /** A boolean latch that determines when the producer for this data item will be allowed to continue. */
+ BooleanLatch latch = new BooleanLatch();
+
+ /** The data element associated with this item. */
+ E element;
+
+ /**
+ * Create a new synch record.
+ *
+ * @param e The data element that the record encapsulates.
+ */
+ public SynchRecordImpl(E e)
+ {
+ // Keep the data element.
+ element = e;
+ }
+
+ /**
+ * Waits until the producer is given permission to proceded by a consumer.
+ */
+ public void waitForConsumer()
+ {
+ latch.await();
+ }
+
+ /**
+ * Gets the data element contained by this record.
+ *
+ * @return The data element contained by this record.
+ */
+ public E getElement()
+ {
+ return element;
+ }
+
+ /**
+ * Immediately releases the producer of this data record. Consumers can bring the synchronization time of
+ * producers to a minimum by using this method to release them at the earliest possible moment when batch
+ * consuming records from sychronized producers.
+ */
+ public void releaseImmediately()
+ {
+ // Check that the record has not already been released, is in error or is to be requeued.
+ latch.signal();
+
+ // Propagate errors to the producer.
+
+ // Requeue items to be requeued.
+ }
+
+ /**
+ * Tells the synch queue to put this element back onto the queue instead of releasing its producer.
+ * The element is not requeued immediately but upon calling the {@link SynchRef#unblockProducers()} method or
+ * the {@link #releaseImmediately()} method.
+ *
+ * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this
+ * element has already been unblocked.
+ */
+ public void reQueue()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Tells the synch queue to raise an exception with this elements producer. The exception is not raised
+ * immediately but upon calling the {@link SynchRef#unblockProducers()} method or the
+ * {@link #releaseImmediately()} method. The exception will be wrapped in a {@link SynchException} before it is
+ * raised on the producer.
+ *
+ * <p/>This method is unusual in that it accepts an exception as an argument. This is non-standard but is used
+ * because the exception is to be passed onto a different thread.
+ *
+ * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this
+ * element has already been unblocked.
+ *
+ * @param e The exception to raise on the producer.
+ */
+ public void inError(Exception e)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BooleanLatch.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BooleanLatch.java
index 2a5b0d0c3e..391ca686c9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BooleanLatch.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/BooleanLatch.java
@@ -1,107 +1,107 @@
-package org.apache.qpid.util.concurrent;
-
-import java.util.concurrent.locks.AbstractQueuedSynchronizer;
-
-/**
- * A BooleanLatch is like a set of traffic lights, where threads can wait at a red light until another thread gives
- * the green light. When threads arrive at the latch it is initially red. They queue up until the green signal is
- * given, at which point they can all acquire the latch in shared mode and continue to run concurrently. Once the latch
- * is signalled it cannot be reset to red again.
- *
- * <p/> The latch uses a {@link java.util.concurrent.locks.AbstractQueuedSynchronizer} to implement its synchronization.
- * This has two internal states, 0 which means that the latch is blocked, and 1 which means that the latch is open.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Block threads until a go signal is given.
- * </table>
- *
- * @todo Might be better to use a countdown latch to count down from 1. Its await method can throw interrupted
- * exception which makes the possibility of interruption more explicit, and provides a reminder to recheck the
- * latch condition before continuing.
- */
-public class BooleanLatch
-{
- /** Holds the synchronizer that provides the thread queueing synchronization. */
- private final Sync sync = new Sync();
-
- /**
- * Tests whether or not the latch has been signalled, that is to say that, the light is green.
- *
- * <p/>This method is non-blocking.
- *
- * @return <tt>true</tt> if the latch may be acquired; the light is green.
- */
- public boolean isSignalled()
- {
- return sync.isSignalled();
- }
-
- /**
- * Waits on the latch until the signal is given and the light is green. If the light is already green then the
- * latch will be acquired and the thread will not have to wait.
- *
- * <p/>This method will block until the go signal is given or the thread is otherwise interrupted. Before carrying
- * out any processing threads that return from this method should confirm that the go signal has really been given
- * on this latch by calling the {@link #isSignalled()} method.
- */
- public void await()
- {
- sync.acquireShared(1);
- }
-
- /**
- * Releases any threads currently waiting on the latch. This flips the light to green allowing any threads that
- * were waiting for this condition to now run.
- *
- * <p/>This method is non-blocking.
- */
- public void signal()
- {
- sync.releaseShared(1);
- }
-
- /**
- * Implements a thread queued synchronizer. The internal state 0 means that the queue is blocked and the internl
- * state 1 means that the queue is released and that all waiting threads can acquire the synchronizer in shared
- * mode.
- */
- private static class Sync extends AbstractQueuedSynchronizer
- {
- /**
- * Attempts to acquire this synchronizer in shared mode. It may be acquired once it has been released.
- *
- * @param ignore This parameter is ignored.
- *
- * @return 1 if the shared acquisition succeeds and -1 if it fails.
- */
- protected int tryAcquireShared(int ignore)
- {
- return isSignalled() ? 1 : -1;
- }
-
- /**
- * Releases the synchronizer, setting its internal state to 1.
- *
- * @param ignore This parameter is ignored.
- *
- * @return <tt>true</tt> always.
- */
- protected boolean tryReleaseShared(int ignore)
- {
- setState(1);
-
- return true;
- }
-
- /**
- * Tests if the synchronizer is signalled. It is signalled when its internal state it 1.
- *
- * @return <tt>true</tt> if the internal state is 1, <tt>false</tt> otherwise.
- */
- boolean isSignalled()
- {
- return getState() != 0;
- }
- }
-}
+package org.apache.qpid.util.concurrent;
+
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+/**
+ * A BooleanLatch is like a set of traffic lights, where threads can wait at a red light until another thread gives
+ * the green light. When threads arrive at the latch it is initially red. They queue up until the green signal is
+ * given, at which point they can all acquire the latch in shared mode and continue to run concurrently. Once the latch
+ * is signalled it cannot be reset to red again.
+ *
+ * <p/> The latch uses a {@link java.util.concurrent.locks.AbstractQueuedSynchronizer} to implement its synchronization.
+ * This has two internal states, 0 which means that the latch is blocked, and 1 which means that the latch is open.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Block threads until a go signal is given.
+ * </table>
+ *
+ * @todo Might be better to use a countdown latch to count down from 1. Its await method can throw interrupted
+ * exception which makes the possibility of interruption more explicit, and provides a reminder to recheck the
+ * latch condition before continuing.
+ */
+public class BooleanLatch
+{
+ /** Holds the synchronizer that provides the thread queueing synchronization. */
+ private final Sync sync = new Sync();
+
+ /**
+ * Tests whether or not the latch has been signalled, that is to say that, the light is green.
+ *
+ * <p/>This method is non-blocking.
+ *
+ * @return <tt>true</tt> if the latch may be acquired; the light is green.
+ */
+ public boolean isSignalled()
+ {
+ return sync.isSignalled();
+ }
+
+ /**
+ * Waits on the latch until the signal is given and the light is green. If the light is already green then the
+ * latch will be acquired and the thread will not have to wait.
+ *
+ * <p/>This method will block until the go signal is given or the thread is otherwise interrupted. Before carrying
+ * out any processing threads that return from this method should confirm that the go signal has really been given
+ * on this latch by calling the {@link #isSignalled()} method.
+ */
+ public void await()
+ {
+ sync.acquireShared(1);
+ }
+
+ /**
+ * Releases any threads currently waiting on the latch. This flips the light to green allowing any threads that
+ * were waiting for this condition to now run.
+ *
+ * <p/>This method is non-blocking.
+ */
+ public void signal()
+ {
+ sync.releaseShared(1);
+ }
+
+ /**
+ * Implements a thread queued synchronizer. The internal state 0 means that the queue is blocked and the internl
+ * state 1 means that the queue is released and that all waiting threads can acquire the synchronizer in shared
+ * mode.
+ */
+ private static class Sync extends AbstractQueuedSynchronizer
+ {
+ /**
+ * Attempts to acquire this synchronizer in shared mode. It may be acquired once it has been released.
+ *
+ * @param ignore This parameter is ignored.
+ *
+ * @return 1 if the shared acquisition succeeds and -1 if it fails.
+ */
+ protected int tryAcquireShared(int ignore)
+ {
+ return isSignalled() ? 1 : -1;
+ }
+
+ /**
+ * Releases the synchronizer, setting its internal state to 1.
+ *
+ * @param ignore This parameter is ignored.
+ *
+ * @return <tt>true</tt> always.
+ */
+ protected boolean tryReleaseShared(int ignore)
+ {
+ setState(1);
+
+ return true;
+ }
+
+ /**
+ * Tests if the synchronizer is signalled. It is signalled when its internal state it 1.
+ *
+ * @return <tt>true</tt> if the internal state is 1, <tt>false</tt> otherwise.
+ */
+ boolean isSignalled()
+ {
+ return getState() != 0;
+ }
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/Capacity.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/Capacity.java
index 2b4a5f28a9..e317c84971 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/Capacity.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/Capacity.java
@@ -1,14 +1,14 @@
-package org.apache.qpid.util.concurrent;
-
-/**
- * An interface exposed by data structures that have a maximum capacity.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Report the maximum capacity.
- * </table>
- */
-public interface Capacity
-{
- public int getCapacity();
-}
+package org.apache.qpid.util.concurrent;
+
+/**
+ * An interface exposed by data structures that have a maximum capacity.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Report the maximum capacity.
+ * </table>
+ */
+public interface Capacity
+{
+ public int getCapacity();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchBuffer.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchBuffer.java
index 8f682ec462..49020803d7 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchBuffer.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchBuffer.java
@@ -1,29 +1,29 @@
-package org.apache.qpid.util.concurrent;
-
-import java.util.Queue;
-
-/**
- * SynchBuffer completes the {@link BatchSynchQueueBase} abstract class by providing an implementation of the underlying
- * queue as an array. This uses FIFO ordering for the queue but restricts the maximum size of the queue to a fixed
- * amount. It also has the advantage that, as the buffer does not grow and shrink dynamically, memory for the buffer
- * is allocated up front and does not create garbage during the operation of the queue.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide array based FIFO queue to create a batch synched queue around.
- * </table>
- *
- * @todo Write an array based buffer implementation that implements Queue.
- */
-public class SynchBuffer<E> extends BatchSynchQueueBase<E>
-{
- /**
- * Returns an empty queue, implemented as an array.
- *
- * @return An empty queue, implemented as an array.
- */
- protected <T> Queue<T> createQueue()
- {
- throw new RuntimeException("Not implemented.");
- }
-}
+package org.apache.qpid.util.concurrent;
+
+import java.util.Queue;
+
+/**
+ * SynchBuffer completes the {@link BatchSynchQueueBase} abstract class by providing an implementation of the underlying
+ * queue as an array. This uses FIFO ordering for the queue but restricts the maximum size of the queue to a fixed
+ * amount. It also has the advantage that, as the buffer does not grow and shrink dynamically, memory for the buffer
+ * is allocated up front and does not create garbage during the operation of the queue.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide array based FIFO queue to create a batch synched queue around.
+ * </table>
+ *
+ * @todo Write an array based buffer implementation that implements Queue.
+ */
+public class SynchBuffer<E> extends BatchSynchQueueBase<E>
+{
+ /**
+ * Returns an empty queue, implemented as an array.
+ *
+ * @return An empty queue, implemented as an array.
+ */
+ protected <T> Queue<T> createQueue()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchException.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchException.java
index c6edff6320..77b60f2b72 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchException.java
@@ -1,31 +1,31 @@
-package org.apache.qpid.util.concurrent;
-
-/**
- * SynchException is used to encapsulate exceptions with the data elements that caused them in order to send exceptions
- * back from the consumers of a {@link BatchSynchQueue} to producers. The underlying exception should be retrieved from
- * the {@link #getCause} method.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Encapsulate a data element and exception.
- * </table>
- */
-public class SynchException extends Exception
-{
- /** Holds the data element that is in error. */
- Object element;
-
- /**
- * Creates a new BaseApplicationException object.
- *
- * @param message The exception message.
- * @param cause The underlying throwable cause. This may be null.
- */
- public SynchException(String message, Throwable cause, Object element)
- {
- super(message, cause);
-
- // Keep the data element that was in error.
- this.element = element;
- }
-}
+package org.apache.qpid.util.concurrent;
+
+/**
+ * SynchException is used to encapsulate exceptions with the data elements that caused them in order to send exceptions
+ * back from the consumers of a {@link BatchSynchQueue} to producers. The underlying exception should be retrieved from
+ * the {@link #getCause} method.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Encapsulate a data element and exception.
+ * </table>
+ */
+public class SynchException extends Exception
+{
+ /** Holds the data element that is in error. */
+ Object element;
+
+ /**
+ * Creates a new BaseApplicationException object.
+ *
+ * @param message The exception message.
+ * @param cause The underlying throwable cause. This may be null.
+ */
+ public SynchException(String message, Throwable cause, Object element)
+ {
+ super(message, cause);
+
+ // Keep the data element that was in error.
+ this.element = element;
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchQueue.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchQueue.java
index df3f2b849a..9d15c211f6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchQueue.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchQueue.java
@@ -1,27 +1,27 @@
-package org.apache.qpid.util.concurrent;
-
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * SynchQueue completes the {@link BatchSynchQueueBase} abstract class by providing an implementation of the underlying
- * queue as a linked list. This uses FIFO ordering for the queue and allows the queue to grow to accomodate more
- * elements as needed.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide linked list FIFO queue to create a batch synched queue around.
- * </table>
- */
-public class SynchQueue<E> extends BatchSynchQueueBase<E>
-{
- /**
- * Returns an empty queue, implemented as a linked list.
- *
- * @return An empty queue, implemented as a linked list.
- */
- protected <T> Queue<T> createQueue()
- {
- return new LinkedList<T>();
- }
-}
+package org.apache.qpid.util.concurrent;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * SynchQueue completes the {@link BatchSynchQueueBase} abstract class by providing an implementation of the underlying
+ * queue as a linked list. This uses FIFO ordering for the queue and allows the queue to grow to accomodate more
+ * elements as needed.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide linked list FIFO queue to create a batch synched queue around.
+ * </table>
+ */
+public class SynchQueue<E> extends BatchSynchQueueBase<E>
+{
+ /**
+ * Returns an empty queue, implemented as a linked list.
+ *
+ * @return An empty queue, implemented as a linked list.
+ */
+ protected <T> Queue<T> createQueue()
+ {
+ return new LinkedList<T>();
+ }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRecord.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRecord.java
index cacef472d6..5e002100c2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRecord.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRecord.java
@@ -1,53 +1,53 @@
-package org.apache.qpid.util.concurrent;
-
-/**
- * SynchRecord associates a data item from a {@link BatchSynchQueue} with its producer. This enables the data item data
- * item to be put back on the queue without unblocking its producer, or to send exceptions to the producer.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Get the underlying data element.
- * <tr><td> Put the data element back on the queue without unblocking its producer.
- * <tr><td> Send and exception to the data elements producer.
- * </table>
- */
-public interface SynchRecord<E>
-{
- /**
- * Gets the data element contained by this record.
- *
- * @return The data element contained by this record.
- */
- public E getElement();
-
- /**
- * Tells the synch queue to put this element back onto the queue instead of releasing its producer.
- * The element is not requeued immediately but upon calling the {@link SynchRef#unblockProducers()} method.
- *
- * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this element
- * has already been unblocked.
- */
- public void reQueue();
-
- /**
- * Immediately releases the producer of this data record. Consumers can bring the synchronization time of
- * producers to a minimum by using this method to release them at the earliest possible moment when batch
- * consuming records from sychronized producers.
- */
- public void releaseImmediately();
-
- /**
- * Tells the synch queue to raise an exception with this elements producer. The exception is not raised immediately
- * but upon calling the {@link SynchRef#unblockProducers()} method. The exception will be wrapped in a
- * {@link SynchException} before it is raised on the producer.
- *
- * <p/>This method is unusual in that it accepts an exception as an argument. This is non-standard but is used
- * because the exception is to be passed onto a different thread.
- *
- * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this element
- * has already been unblocked.
- *
- * @param e The exception to raise on the producer.
- */
- public void inError(Exception e);
-}
+package org.apache.qpid.util.concurrent;
+
+/**
+ * SynchRecord associates a data item from a {@link BatchSynchQueue} with its producer. This enables the data item data
+ * item to be put back on the queue without unblocking its producer, or to send exceptions to the producer.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Get the underlying data element.
+ * <tr><td> Put the data element back on the queue without unblocking its producer.
+ * <tr><td> Send and exception to the data elements producer.
+ * </table>
+ */
+public interface SynchRecord<E>
+{
+ /**
+ * Gets the data element contained by this record.
+ *
+ * @return The data element contained by this record.
+ */
+ public E getElement();
+
+ /**
+ * Tells the synch queue to put this element back onto the queue instead of releasing its producer.
+ * The element is not requeued immediately but upon calling the {@link SynchRef#unblockProducers()} method.
+ *
+ * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this element
+ * has already been unblocked.
+ */
+ public void reQueue();
+
+ /**
+ * Immediately releases the producer of this data record. Consumers can bring the synchronization time of
+ * producers to a minimum by using this method to release them at the earliest possible moment when batch
+ * consuming records from sychronized producers.
+ */
+ public void releaseImmediately();
+
+ /**
+ * Tells the synch queue to raise an exception with this elements producer. The exception is not raised immediately
+ * but upon calling the {@link SynchRef#unblockProducers()} method. The exception will be wrapped in a
+ * {@link SynchException} before it is raised on the producer.
+ *
+ * <p/>This method is unusual in that it accepts an exception as an argument. This is non-standard but is used
+ * because the exception is to be passed onto a different thread.
+ *
+ * <p/>This method will raise a runtime exception {@link AlreadyUnblockedException} if the producer for this element
+ * has already been unblocked.
+ *
+ * @param e The exception to raise on the producer.
+ */
+ public void inError(Exception e);
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRef.java b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRef.java
index c044ed0a60..a75f7b766d 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRef.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/util/concurrent/SynchRef.java
@@ -1,30 +1,30 @@
-package org.apache.qpid.util.concurrent;
-
-/**
- * A SynchRef is an interface which is returned from the synchronous take and drain methods of {@link BatchSynchQueue},
- * allowing call-backs to be made against the synchronizing strucutre. It allows the consumer to communicate when it
- * wants producers that have their data taken to be unblocked.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Report number of records returned by a taking operation.
- * <tr><td> Provide call-back to release producers of taken records.
- * </table>
- */
-public interface SynchRef
-{
- /**
- * Reports the number of records taken by the take or drain operation.
- *
- * @return The number of records taken by the take or drain operation.
- */
- public int getNumRecords();
-
- /**
- * Any producers that have had their data elements taken from the queue but have not been unblocked are
- * unblocked when this method is called. The exception to this is producers that have had their data put back
- * onto the queue by a consumer. Producers that have had exceptions for their data items registered by consumers
- * will be unblocked but will not return from their put call normally, but with an exception instead.
- */
- public void unblockProducers();
-}
+package org.apache.qpid.util.concurrent;
+
+/**
+ * A SynchRef is an interface which is returned from the synchronous take and drain methods of {@link BatchSynchQueue},
+ * allowing call-backs to be made against the synchronizing strucutre. It allows the consumer to communicate when it
+ * wants producers that have their data taken to be unblocked.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Report number of records returned by a taking operation.
+ * <tr><td> Provide call-back to release producers of taken records.
+ * </table>
+ */
+public interface SynchRef
+{
+ /**
+ * Reports the number of records taken by the take or drain operation.
+ *
+ * @return The number of records taken by the take or drain operation.
+ */
+ public int getNumRecords();
+
+ /**
+ * Any producers that have had their data elements taken from the queue but have not been unblocked are
+ * unblocked when this method is called. The exception to this is producers that have had their data put back
+ * onto the queue by a consumer. Producers that have had exceptions for their data items registered by consumers
+ * will be unblocked but will not return from their put call normally, but with an exception instead.
+ */
+ public void unblockProducers();
+}
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/util/CommandLineParserTest.java b/qpid/java/common/src/test/java/org/apache/qpid/util/CommandLineParserTest.java
index 66fb3252df..942901f1c0 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/util/CommandLineParserTest.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/util/CommandLineParserTest.java
@@ -1,554 +1,554 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.util;
-
-import junit.framework.*;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Properties;
-
-/**
- * Unit tests the {@link CommandLineParser} class.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check that parsing a single flag works ok.
- * <tr><td> Check that parsing multiple flags condensed together works ok.
- * <tr><td> Check that parsing an option with a space between it and its argument works ok.
- * <tr><td> Check that parsing an option with no space between it and its argument works ok.
- * <tr><td> Check that parsing an option with specific argument format works ok.
- * <tr><td> Check that parsing an option with specific argument format fails on bad argument.
- * <tr><td> Check that parsing a flag condensed together with an option fails.
- * <tr><td> Check that parsing a free argument works ok.
- * <tr><td> Check that parsing a free argument with specific format works ok.
- * <tr><td> Check that parsing a free argument with specific format fails on bad argument.
- * <tr><td> Check that parsing a mandatory option works ok.
- * <tr><td> Check that parsing a mandatory free argument works ok.
- * <tr><td> Check that parsing a mandatory option fails when no option is set.
- * <tr><td> Check that parsing a mandatory free argument fails when no argument is specified.
- * <tr><td> Check that parsing an unknown option works when unknowns not errors.
- * <tr><td> Check that parsing an unknown flag fails when unknowns are to be reported as errors.
- * <tr><td> Check that parsing an unknown option fails when unknowns are to be reported as errors.
- * <tr><td> Check that get errors returns a string on errors.
- * <tr><td> Check that get errors returns an empty string on no errors.
- * <tr><td> Check that get usage returns a string.
- * <tr><td> Check that get options in force returns an empty string before parsing.
- * <tr><td> Check that get options in force return a non-empty string after parsing.
- * </table>
- */
-public class CommandLineParserTest extends TestCase
-{
- private static final Logger log = LoggerFactory.getLogger(CommandLineParserTest.class);
-
- public CommandLineParserTest(String name)
- {
- super(name);
- }
-
- /**
- * Compile all the tests for the default test implementation of a traversable state into a test suite.
- */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("CommandLineParser Tests");
-
- // Add all the tests defined in this class (using the default constructor)
- suite.addTestSuite(CommandLineParserTest.class);
-
- return suite;
- }
-
- /** Check that get errors returns an empty string on no errors. */
- public void testGetErrorsReturnsEmptyStringOnNoErrors() throws Exception
- {
- // Create a command line parser for some flags and options.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" },
- { "t3", "Test Option 3.", "test", "true" },
- { "t4", "Test Option 4.", "test", null, "^test$" }
- });
-
- // Do some legal parsing.
- parser.parseCommandLine(new String[] { "-t1", "-t2test", "-t3test", "-t4test" });
-
- // Check that the get errors message returns an empty string.
- assertTrue("The errors method did not return an empty string.", "".equals(parser.getErrors()));
- }
-
- /** Check that get errors returns a string on errors. */
- public void testGetErrorsReturnsStringOnErrors() throws Exception
- {
- // Create a command line parser for some flags and options.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" },
- { "t3", "Test Option 3.", "test", "true" },
- { "t4", "Test Option 4.", "test", null, "^test$" }
- });
-
- try
- {
- // Do some illegal parsing.
- parser.parseCommandLine(new String[] { "-t1", "-t1t2test", "-t4fail" });
- }
- catch (IllegalArgumentException e)
- { }
-
- // Check that the get errors message returns a string.
- assertTrue("The errors method returned an empty string.",
- !((parser.getErrors() == null) || "".equals(parser.getErrors())));
-
- }
-
- /** Check that get options in force returns an empty string before parsing. */
- public void testGetOptionsInForceReturnsEmptyStringBeforeParsing() throws Exception
- {
- // Create a command line parser for some flags and options.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" },
- { "t3", "Test Option 3.", "test", "true" },
- { "t4", "Test Option 4.", "test", null, "^test$" }
- });
-
- // Check that the options in force method returns an empty string.
- assertTrue("The options in force method did not return an empty string.", "".equals(parser.getOptionsInForce()));
- }
-
- /** Check that get options in force return a non-empty string after parsing. */
- public void testGetOptionsInForceReturnsNonEmptyStringAfterParsing() throws Exception
- {
- // Create a command line parser for some flags and options.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" },
- { "t3", "Test Option 3.", "test", "true" },
- { "t4", "Test Option 4.", "test", null, "^test$" }
- });
-
- // Do some parsing.
- parser.parseCommandLine(new String[] { "-t1", "-t2test", "-t3test", "-t4test" });
-
- // Check that the options in force method returns a string.
- assertTrue("The options in force method did not return a non empty string.",
- !((parser.getOptionsInForce() == null) || "".equals(parser.getOptionsInForce())));
- }
-
- /** Check that get usage returns a string. */
- public void testGetUsageReturnsString() throws Exception
- {
- // Create a command line parser for some flags and options.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" },
- { "t3", "Test Option 3.", "test", "true" },
- { "t4", "Test Option 4.", "test", null, "^test$" }
- });
-
- // Check that the usage method returns a string.
- assertTrue("The usage method did not return a non empty string.",
- !((parser.getUsage() == null) || "".equals(parser.getUsage())));
- }
-
- /** Check that parsing multiple flags condensed together works ok. */
- public void testParseCondensedFlagsOk() throws Exception
- {
- // Create a command line parser for multiple flags.
- CommandLineParser parser =
- new CommandLineParser(
- new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Flag 2." },
- { "t3", "Test Flag 3." }
- });
-
- // Parse a command line with the flags set and condensed together.
- Properties testProps = parser.parseCommandLine(new String[] { "-t1t2t3" });
-
- // Check that the flags were set in the parsed properties.
- assertTrue("The t1 flag was not \"true\", it was: " + testProps.get("t1"), "true".equals(testProps.get("t1")));
- assertTrue("The t2 flag was not \"true\", it was: " + testProps.get("t2"), "true".equals(testProps.get("t2")));
- assertTrue("The t3 flag was not \"true\", it was: " + testProps.get("t3"), "true".equals(testProps.get("t3")));
- }
-
- /** Check that parsing a flag condensed together with an option fails. */
- public void testParseFlagCondensedWithOptionFails() throws Exception
- {
- // Create a command line parser for a flag and an option.
- CommandLineParser parser =
- new CommandLineParser(new String[][]
- {
- { "t1", "Test Flag 1." },
- { "t2", "Test Option 2.", "test" }
- });
-
- // Check that the parser reports an error.
- boolean testPassed = false;
-
- try
- {
- // Parse a command line with the flag and option condensed together.
- Properties testProps = parser.parseCommandLine(new String[] { "-t1t2" });
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- assertTrue("IllegalArgumentException not thrown when a flag and option are condensed together.", testPassed);
- }
-
- /** Check that parsing a free argument with specific format fails on bad argument. */
- public void testParseFormattedFreeArgumentFailsBadArgument() throws Exception
- {
- // Create a command line parser for a formatted free argument.
- CommandLineParser parser =
- new CommandLineParser(new String[][]
- {
- { "1", "Test Free Argument.", "test", null, "^test$" }
- });
-
- // Check that the parser signals an error for a badly formatted argument.
- boolean testPassed = false;
-
- try
- {
- // Parse a command line with this option set incorrectly.
- Properties testProps = parser.parseCommandLine(new String[] { "fail" });
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- assertTrue("IllegalArgumentException not thrown when a badly formatted argument was set.", testPassed);
- }
-
- /** Check that parsing a free argument with specific format works ok. */
- public void testParseFormattedFreeArgumentOk() throws Exception
- {
- // Create a command line parser for a formatted free argument.
- CommandLineParser parser =
- new CommandLineParser(new String[][]
- {
- { "1", "Test Free Argument.", "test", null, "^test$" }
- });
-
- // Parse a command line with this argument set correctly.
- Properties testProps = parser.parseCommandLine(new String[] { "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
- "test".equals(testProps.get("1")));
- }
-
- /** Check that parsing an option with specific argument format fails on bad argument. */
- public void testParseFormattedOptionArgumentFailsBadArgument() throws Exception
- {
- // Create a command line parser for a formatted option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test", null, "^test$" }
- });
-
- // Check that the parser signals an error for a badly formatted argument.
- boolean testPassed = false;
-
- try
- {
- // Parse a command line with this option set incorrectly.
- Properties testProps = parser.parseCommandLine(new String[] { "-t", "fail" });
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- assertTrue("IllegalArgumentException not thrown when a badly formatted argument was set.", testPassed);
- }
-
- /** Check that parsing an option with specific argument format works ok. */
- public void testParseFormattedOptionArgumentOk() throws Exception
- {
- // Create a command line parser for a formatted option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test", null, "^test$" }
- });
-
- // Parse a command line with this option set correctly.
- Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
- "test".equals(testProps.get("t")));
- }
-
- /** Check that parsing a free argument works ok. */
- public void testParseFreeArgumentOk() throws Exception
- {
- // Create a command line parser for a free argument.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "1", "Test Free Argument.", "test" }
- });
-
- // Parse a command line with this argument set.
- Properties testProps = parser.parseCommandLine(new String[] { "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
- "test".equals(testProps.get("1")));
- }
-
- /** Check that parsing a mandatory option works ok. */
- public void testParseMandatoryOptionOk() throws Exception
- {
- // Create a command line parser for a mandatory option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test", "true" }
- });
-
- // Parse a command line with this option set correctly.
- Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
- "test".equals(testProps.get("t")));
- }
-
- /** Check that parsing a mandatory free argument works ok. */
- public void testParseMandatoryFreeArgumentOk() throws Exception
- {
- // Create a command line parser for a mandatory free argument.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "1", "Test Option.", "test", "true" }
- });
-
- // Parse a command line with this argument set.
- Properties testProps = parser.parseCommandLine(new String[] { "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
- "test".equals(testProps.get("1")));
- }
-
- /** Check that parsing a mandatory free argument fails when no argument is specified. */
- public void testParseManadatoryFreeArgumentFailsNoArgument() throws Exception
- {
- // Create a command line parser for a mandatory free argument.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "1", "Test Option.", "test", "true" }
- });
-
- // Check that parsing fails when this mandatory free argument is missing.
- boolean testPassed = false;
-
- try
- {
- // Parse a command line with this free argument not set.
- Properties testProps = parser.parseCommandLine(new String[] {});
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("IllegalArgumentException not thrown for a missing mandatory option.", testPassed);
- }
-
- /** Check that parsing a mandatory option fails when no option is set. */
- public void testParseMandatoryFailsNoOption() throws Exception
- {
- // Create a command line parser for a mandatory option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test", "true" }
- });
-
- // Check that parsing fails when this mandatory option is missing.
- boolean testPassed = false;
-
- try
- {
- // Parse a command line with this option not set.
- Properties testProps = parser.parseCommandLine(new String[] {});
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("IllegalArgumentException not thrown for a missing mandatory option.", testPassed);
- }
-
- /** Check that parsing an option with no space between it and its argument works ok. */
- public void testParseOptionWithNoSpaceOk() throws Exception
- {
- // Create a command line parser for an option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test" }
- });
-
- // Parse a command line with this option set with no space.
- Properties testProps = parser.parseCommandLine(new String[] { "-ttest" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
- "test".equals(testProps.get("t")));
- }
-
- /** Check that parsing an option with a space between it and its argument works ok. */
- public void testParseOptionWithSpaceOk() throws Exception
- {
- // Create a command line parser for an option.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Option.", "test" }
- });
-
- // Parse a command line with this option set with a space.
- Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
-
- // Check that the resultant properties contains the correctly parsed option.
- assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
- "test".equals(testProps.get("t")));
- }
-
- /** Check that parsing a single flag works ok. */
- public void testParseSingleFlagOk() throws Exception
- {
- // Create a command line parser for a single flag.
- CommandLineParser parser = new CommandLineParser(new String[][]
- {
- { "t", "Test Flag." }
- });
-
- // Parse a command line with the single flag set.
- Properties testProps = parser.parseCommandLine(new String[] { "-t" });
-
- // Check that the flag is set in the parsed properties.
- assertTrue("The t flag was not \"true\", it was: " + testProps.get("t"), "true".equals(testProps.get("t")));
-
- // Reset the parser.
- parser.reset();
-
- // Parse a command line with the single flag not set.
- testProps = parser.parseCommandLine(new String[] {});
-
- // Check that the flag is cleared in the parsed properties.
- assertTrue("The t flag was not \"false\", it was: " + testProps.get("t"), "false".equals(testProps.get("t")));
- }
-
- /** Check that parsing an unknown option works when unknowns not errors. */
- public void testParseUnknownOptionOk() throws Exception
- {
- // Create a command line parser for no flags or options
- CommandLineParser parser = new CommandLineParser(new String[][] {});
-
- // Check that parsing does not fail on an unknown flag.
- try
- {
- parser.parseCommandLine(new String[] { "-t" });
- }
- catch (IllegalArgumentException e)
- {
- fail("The parser threw an IllegalArgumentException on an unknown flag when errors on unkowns is off.");
- }
- }
-
- /** Check that parsing an unknown flag fails when unknowns are to be reported as errors. */
- public void testParseUnknownFlagFailsWhenUnknownsAreErrors() throws Exception
- {
- // Create a command line parser for no flags or options
- CommandLineParser parser = new CommandLineParser(new String[][] {});
-
- // Turn on fail on unknowns mode.
- parser.setErrorsOnUnknowns(true);
-
- // Check that parsing fails on an unknown flag.
- boolean testPassed = false;
-
- try
- {
- parser.parseCommandLine(new String[] { "-t" });
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- assertTrue("IllegalArgumentException not thrown for an unknown flag when errors on unknowns mode is on.",
- testPassed);
- }
-
- /** Check that parsing an unknown option fails when unknowns are to be reported as errors. */
- public void testParseUnknownOptionFailsWhenUnknownsAreErrors() throws Exception
- {
- // Create a command line parser for no flags or options
- CommandLineParser parser = new CommandLineParser(new String[][] {});
-
- // Turn on fail on unknowns mode.
- parser.setErrorsOnUnknowns(true);
-
- // Check that parsing fails on an unknown flag.
- boolean testPassed = false;
-
- try
- {
- parser.parseCommandLine(new String[] { "-t", "test" });
- }
- catch (IllegalArgumentException e)
- {
- testPassed = true;
- }
-
- assertTrue("IllegalArgumentException not thrown for an unknown option when errors on unknowns mode is on.",
- testPassed);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.util;
+
+import junit.framework.*;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Properties;
+
+/**
+ * Unit tests the {@link CommandLineParser} class.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check that parsing a single flag works ok.
+ * <tr><td> Check that parsing multiple flags condensed together works ok.
+ * <tr><td> Check that parsing an option with a space between it and its argument works ok.
+ * <tr><td> Check that parsing an option with no space between it and its argument works ok.
+ * <tr><td> Check that parsing an option with specific argument format works ok.
+ * <tr><td> Check that parsing an option with specific argument format fails on bad argument.
+ * <tr><td> Check that parsing a flag condensed together with an option fails.
+ * <tr><td> Check that parsing a free argument works ok.
+ * <tr><td> Check that parsing a free argument with specific format works ok.
+ * <tr><td> Check that parsing a free argument with specific format fails on bad argument.
+ * <tr><td> Check that parsing a mandatory option works ok.
+ * <tr><td> Check that parsing a mandatory free argument works ok.
+ * <tr><td> Check that parsing a mandatory option fails when no option is set.
+ * <tr><td> Check that parsing a mandatory free argument fails when no argument is specified.
+ * <tr><td> Check that parsing an unknown option works when unknowns not errors.
+ * <tr><td> Check that parsing an unknown flag fails when unknowns are to be reported as errors.
+ * <tr><td> Check that parsing an unknown option fails when unknowns are to be reported as errors.
+ * <tr><td> Check that get errors returns a string on errors.
+ * <tr><td> Check that get errors returns an empty string on no errors.
+ * <tr><td> Check that get usage returns a string.
+ * <tr><td> Check that get options in force returns an empty string before parsing.
+ * <tr><td> Check that get options in force return a non-empty string after parsing.
+ * </table>
+ */
+public class CommandLineParserTest extends TestCase
+{
+ private static final Logger log = LoggerFactory.getLogger(CommandLineParserTest.class);
+
+ public CommandLineParserTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Compile all the tests for the default test implementation of a traversable state into a test suite.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("CommandLineParser Tests");
+
+ // Add all the tests defined in this class (using the default constructor)
+ suite.addTestSuite(CommandLineParserTest.class);
+
+ return suite;
+ }
+
+ /** Check that get errors returns an empty string on no errors. */
+ public void testGetErrorsReturnsEmptyStringOnNoErrors() throws Exception
+ {
+ // Create a command line parser for some flags and options.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" },
+ { "t3", "Test Option 3.", "test", "true" },
+ { "t4", "Test Option 4.", "test", null, "^test$" }
+ });
+
+ // Do some legal parsing.
+ parser.parseCommandLine(new String[] { "-t1", "-t2test", "-t3test", "-t4test" });
+
+ // Check that the get errors message returns an empty string.
+ assertTrue("The errors method did not return an empty string.", "".equals(parser.getErrors()));
+ }
+
+ /** Check that get errors returns a string on errors. */
+ public void testGetErrorsReturnsStringOnErrors() throws Exception
+ {
+ // Create a command line parser for some flags and options.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" },
+ { "t3", "Test Option 3.", "test", "true" },
+ { "t4", "Test Option 4.", "test", null, "^test$" }
+ });
+
+ try
+ {
+ // Do some illegal parsing.
+ parser.parseCommandLine(new String[] { "-t1", "-t1t2test", "-t4fail" });
+ }
+ catch (IllegalArgumentException e)
+ { }
+
+ // Check that the get errors message returns a string.
+ assertTrue("The errors method returned an empty string.",
+ !((parser.getErrors() == null) || "".equals(parser.getErrors())));
+
+ }
+
+ /** Check that get options in force returns an empty string before parsing. */
+ public void testGetOptionsInForceReturnsEmptyStringBeforeParsing() throws Exception
+ {
+ // Create a command line parser for some flags and options.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" },
+ { "t3", "Test Option 3.", "test", "true" },
+ { "t4", "Test Option 4.", "test", null, "^test$" }
+ });
+
+ // Check that the options in force method returns an empty string.
+ assertTrue("The options in force method did not return an empty string.", "".equals(parser.getOptionsInForce()));
+ }
+
+ /** Check that get options in force return a non-empty string after parsing. */
+ public void testGetOptionsInForceReturnsNonEmptyStringAfterParsing() throws Exception
+ {
+ // Create a command line parser for some flags and options.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" },
+ { "t3", "Test Option 3.", "test", "true" },
+ { "t4", "Test Option 4.", "test", null, "^test$" }
+ });
+
+ // Do some parsing.
+ parser.parseCommandLine(new String[] { "-t1", "-t2test", "-t3test", "-t4test" });
+
+ // Check that the options in force method returns a string.
+ assertTrue("The options in force method did not return a non empty string.",
+ !((parser.getOptionsInForce() == null) || "".equals(parser.getOptionsInForce())));
+ }
+
+ /** Check that get usage returns a string. */
+ public void testGetUsageReturnsString() throws Exception
+ {
+ // Create a command line parser for some flags and options.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" },
+ { "t3", "Test Option 3.", "test", "true" },
+ { "t4", "Test Option 4.", "test", null, "^test$" }
+ });
+
+ // Check that the usage method returns a string.
+ assertTrue("The usage method did not return a non empty string.",
+ !((parser.getUsage() == null) || "".equals(parser.getUsage())));
+ }
+
+ /** Check that parsing multiple flags condensed together works ok. */
+ public void testParseCondensedFlagsOk() throws Exception
+ {
+ // Create a command line parser for multiple flags.
+ CommandLineParser parser =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Flag 2." },
+ { "t3", "Test Flag 3." }
+ });
+
+ // Parse a command line with the flags set and condensed together.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t1t2t3" });
+
+ // Check that the flags were set in the parsed properties.
+ assertTrue("The t1 flag was not \"true\", it was: " + testProps.get("t1"), "true".equals(testProps.get("t1")));
+ assertTrue("The t2 flag was not \"true\", it was: " + testProps.get("t2"), "true".equals(testProps.get("t2")));
+ assertTrue("The t3 flag was not \"true\", it was: " + testProps.get("t3"), "true".equals(testProps.get("t3")));
+ }
+
+ /** Check that parsing a flag condensed together with an option fails. */
+ public void testParseFlagCondensedWithOptionFails() throws Exception
+ {
+ // Create a command line parser for a flag and an option.
+ CommandLineParser parser =
+ new CommandLineParser(new String[][]
+ {
+ { "t1", "Test Flag 1." },
+ { "t2", "Test Option 2.", "test" }
+ });
+
+ // Check that the parser reports an error.
+ boolean testPassed = false;
+
+ try
+ {
+ // Parse a command line with the flag and option condensed together.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t1t2" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ assertTrue("IllegalArgumentException not thrown when a flag and option are condensed together.", testPassed);
+ }
+
+ /** Check that parsing a free argument with specific format fails on bad argument. */
+ public void testParseFormattedFreeArgumentFailsBadArgument() throws Exception
+ {
+ // Create a command line parser for a formatted free argument.
+ CommandLineParser parser =
+ new CommandLineParser(new String[][]
+ {
+ { "1", "Test Free Argument.", "test", null, "^test$" }
+ });
+
+ // Check that the parser signals an error for a badly formatted argument.
+ boolean testPassed = false;
+
+ try
+ {
+ // Parse a command line with this option set incorrectly.
+ Properties testProps = parser.parseCommandLine(new String[] { "fail" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ assertTrue("IllegalArgumentException not thrown when a badly formatted argument was set.", testPassed);
+ }
+
+ /** Check that parsing a free argument with specific format works ok. */
+ public void testParseFormattedFreeArgumentOk() throws Exception
+ {
+ // Create a command line parser for a formatted free argument.
+ CommandLineParser parser =
+ new CommandLineParser(new String[][]
+ {
+ { "1", "Test Free Argument.", "test", null, "^test$" }
+ });
+
+ // Parse a command line with this argument set correctly.
+ Properties testProps = parser.parseCommandLine(new String[] { "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
+ "test".equals(testProps.get("1")));
+ }
+
+ /** Check that parsing an option with specific argument format fails on bad argument. */
+ public void testParseFormattedOptionArgumentFailsBadArgument() throws Exception
+ {
+ // Create a command line parser for a formatted option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test", null, "^test$" }
+ });
+
+ // Check that the parser signals an error for a badly formatted argument.
+ boolean testPassed = false;
+
+ try
+ {
+ // Parse a command line with this option set incorrectly.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t", "fail" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ assertTrue("IllegalArgumentException not thrown when a badly formatted argument was set.", testPassed);
+ }
+
+ /** Check that parsing an option with specific argument format works ok. */
+ public void testParseFormattedOptionArgumentOk() throws Exception
+ {
+ // Create a command line parser for a formatted option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test", null, "^test$" }
+ });
+
+ // Parse a command line with this option set correctly.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
+ "test".equals(testProps.get("t")));
+ }
+
+ /** Check that parsing a free argument works ok. */
+ public void testParseFreeArgumentOk() throws Exception
+ {
+ // Create a command line parser for a free argument.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "1", "Test Free Argument.", "test" }
+ });
+
+ // Parse a command line with this argument set.
+ Properties testProps = parser.parseCommandLine(new String[] { "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
+ "test".equals(testProps.get("1")));
+ }
+
+ /** Check that parsing a mandatory option works ok. */
+ public void testParseMandatoryOptionOk() throws Exception
+ {
+ // Create a command line parser for a mandatory option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test", "true" }
+ });
+
+ // Parse a command line with this option set correctly.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
+ "test".equals(testProps.get("t")));
+ }
+
+ /** Check that parsing a mandatory free argument works ok. */
+ public void testParseMandatoryFreeArgumentOk() throws Exception
+ {
+ // Create a command line parser for a mandatory free argument.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "1", "Test Option.", "test", "true" }
+ });
+
+ // Parse a command line with this argument set.
+ Properties testProps = parser.parseCommandLine(new String[] { "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The first free argument was not equal to \"test\" but was: " + testProps.get("1"),
+ "test".equals(testProps.get("1")));
+ }
+
+ /** Check that parsing a mandatory free argument fails when no argument is specified. */
+ public void testParseManadatoryFreeArgumentFailsNoArgument() throws Exception
+ {
+ // Create a command line parser for a mandatory free argument.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "1", "Test Option.", "test", "true" }
+ });
+
+ // Check that parsing fails when this mandatory free argument is missing.
+ boolean testPassed = false;
+
+ try
+ {
+ // Parse a command line with this free argument not set.
+ Properties testProps = parser.parseCommandLine(new String[] {});
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("IllegalArgumentException not thrown for a missing mandatory option.", testPassed);
+ }
+
+ /** Check that parsing a mandatory option fails when no option is set. */
+ public void testParseMandatoryFailsNoOption() throws Exception
+ {
+ // Create a command line parser for a mandatory option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test", "true" }
+ });
+
+ // Check that parsing fails when this mandatory option is missing.
+ boolean testPassed = false;
+
+ try
+ {
+ // Parse a command line with this option not set.
+ Properties testProps = parser.parseCommandLine(new String[] {});
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("IllegalArgumentException not thrown for a missing mandatory option.", testPassed);
+ }
+
+ /** Check that parsing an option with no space between it and its argument works ok. */
+ public void testParseOptionWithNoSpaceOk() throws Exception
+ {
+ // Create a command line parser for an option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test" }
+ });
+
+ // Parse a command line with this option set with no space.
+ Properties testProps = parser.parseCommandLine(new String[] { "-ttest" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
+ "test".equals(testProps.get("t")));
+ }
+
+ /** Check that parsing an option with a space between it and its argument works ok. */
+ public void testParseOptionWithSpaceOk() throws Exception
+ {
+ // Create a command line parser for an option.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Option.", "test" }
+ });
+
+ // Parse a command line with this option set with a space.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t", "test" });
+
+ // Check that the resultant properties contains the correctly parsed option.
+ assertTrue("The test option was not equal to \"test\" but was: " + testProps.get("t"),
+ "test".equals(testProps.get("t")));
+ }
+
+ /** Check that parsing a single flag works ok. */
+ public void testParseSingleFlagOk() throws Exception
+ {
+ // Create a command line parser for a single flag.
+ CommandLineParser parser = new CommandLineParser(new String[][]
+ {
+ { "t", "Test Flag." }
+ });
+
+ // Parse a command line with the single flag set.
+ Properties testProps = parser.parseCommandLine(new String[] { "-t" });
+
+ // Check that the flag is set in the parsed properties.
+ assertTrue("The t flag was not \"true\", it was: " + testProps.get("t"), "true".equals(testProps.get("t")));
+
+ // Reset the parser.
+ parser.reset();
+
+ // Parse a command line with the single flag not set.
+ testProps = parser.parseCommandLine(new String[] {});
+
+ // Check that the flag is cleared in the parsed properties.
+ assertTrue("The t flag was not \"false\", it was: " + testProps.get("t"), "false".equals(testProps.get("t")));
+ }
+
+ /** Check that parsing an unknown option works when unknowns not errors. */
+ public void testParseUnknownOptionOk() throws Exception
+ {
+ // Create a command line parser for no flags or options
+ CommandLineParser parser = new CommandLineParser(new String[][] {});
+
+ // Check that parsing does not fail on an unknown flag.
+ try
+ {
+ parser.parseCommandLine(new String[] { "-t" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ fail("The parser threw an IllegalArgumentException on an unknown flag when errors on unkowns is off.");
+ }
+ }
+
+ /** Check that parsing an unknown flag fails when unknowns are to be reported as errors. */
+ public void testParseUnknownFlagFailsWhenUnknownsAreErrors() throws Exception
+ {
+ // Create a command line parser for no flags or options
+ CommandLineParser parser = new CommandLineParser(new String[][] {});
+
+ // Turn on fail on unknowns mode.
+ parser.setErrorsOnUnknowns(true);
+
+ // Check that parsing fails on an unknown flag.
+ boolean testPassed = false;
+
+ try
+ {
+ parser.parseCommandLine(new String[] { "-t" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ assertTrue("IllegalArgumentException not thrown for an unknown flag when errors on unknowns mode is on.",
+ testPassed);
+ }
+
+ /** Check that parsing an unknown option fails when unknowns are to be reported as errors. */
+ public void testParseUnknownOptionFailsWhenUnknownsAreErrors() throws Exception
+ {
+ // Create a command line parser for no flags or options
+ CommandLineParser parser = new CommandLineParser(new String[][] {});
+
+ // Turn on fail on unknowns mode.
+ parser.setErrorsOnUnknowns(true);
+
+ // Check that parsing fails on an unknown flag.
+ boolean testPassed = false;
+
+ try
+ {
+ parser.parseCommandLine(new String[] { "-t", "test" });
+ }
+ catch (IllegalArgumentException e)
+ {
+ testPassed = true;
+ }
+
+ assertTrue("IllegalArgumentException not thrown for an unknown option when errors on unknowns mode is on.",
+ testPassed);
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java
index 45bbfcd148..db17c7aacc 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase1DummyRun.java
@@ -1,135 +1,135 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.clienttestcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.Session;
-
-/**
- * Implements tet case 1, dummy run. This test case sends no test messages, it exists to confirm that the test harness
- * is interacting with the coordinator correctly.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Perform test case actions.
- * <tr><td> Generate test reports.
- * </table>
- */
-public class TestCase1DummyRun implements TestClientControlledTest
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestCase1DummyRun.class);
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the
- * interop testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "TC1_DummyRun";
- }
-
- /**
- * Determines whether the test invite that matched this test case is acceptable.
- *
- * @param inviteMessage The invitation to accept or reject.
- *
- * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public boolean acceptInvite(Message inviteMessage) throws JMSException
- {
- log.debug("public boolean acceptInvite(Message inviteMessage): called");
-
- // Test parameters don't matter, accept all invites.
- return true;
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the
- * assignment message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role, Message assignRoleMessage): called");
-
- // Do nothing, both roles are the same.
- }
-
- /**
- * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
- *
- * @param numMessages The number of test messages to send.
- */
- public void start(int numMessages)
- {
- log.debug("public void start(): called");
-
- // Do nothing.
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Generate a dummy report, the coordinator expects a report but doesn't care what it is.
- return session.createTextMessage("Dummy Run, Ok.");
- }
-
- /**
- * Handles incoming test messages. Does nothing.
- *
- * @param message The incoming test message.
- */
- public void onMessage(Message message)
- {
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- // Ignore any messages.
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.clienttestcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+/**
+ * Implements tet case 1, dummy run. This test case sends no test messages, it exists to confirm that the test harness
+ * is interacting with the coordinator correctly.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Perform test case actions.
+ * <tr><td> Generate test reports.
+ * </table>
+ */
+public class TestCase1DummyRun implements TestClientControlledTest
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestCase1DummyRun.class);
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the
+ * interop testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "TC1_DummyRun";
+ }
+
+ /**
+ * Determines whether the test invite that matched this test case is acceptable.
+ *
+ * @param inviteMessage The invitation to accept or reject.
+ *
+ * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public boolean acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public boolean acceptInvite(Message inviteMessage): called");
+
+ // Test parameters don't matter, accept all invites.
+ return true;
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the
+ * assignment message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role, Message assignRoleMessage): called");
+
+ // Do nothing, both roles are the same.
+ }
+
+ /**
+ * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ *
+ * @param numMessages The number of test messages to send.
+ */
+ public void start(int numMessages)
+ {
+ log.debug("public void start(): called");
+
+ // Do nothing.
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Generate a dummy report, the coordinator expects a report but doesn't care what it is.
+ return session.createTextMessage("Dummy Run, Ok.");
+ }
+
+ /**
+ * Handles incoming test messages. Does nothing.
+ *
+ * @param message The incoming test message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ // Ignore any messages.
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java
index 1d30ff7ca6..36d3cce7f7 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase2BasicP2P.java
@@ -1,209 +1,209 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.clienttestcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.distributedtesting.TestClient;
-import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-
-import javax.jms.*;
-
-/**
- * Implements test case 2, basic P2P. Sends/received a specified number of messages to a specified route on the
- * default direct exchange. Produces reports on the actual number of messages sent/received.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Send required number of test messages.
- * <tr><td> Generate test reports.
- * </table>
- */
-public class TestCase2BasicP2P implements TestClientControlledTest, MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestCase2BasicP2P.class);
-
- /** Holds the count of test messages received. */
- private int messageCount;
-
- /** The role to be played by the test. */
- private Roles role;
-
- /** The number of test messages to send. */
- private int numMessages;
-
- /** The connection to send the test messages on. */
- private Connection connection;
-
- /** The controlSession to send the test messages on. */
- private Session session;
-
- /** The producer to send the test messages with. */
- MessageProducer producer;
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the
- * interop testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "TC2_BasicP2P";
- }
-
- /**
- * Determines whether the test invite that matched this test case is acceptable.
- *
- * @param inviteMessage The invitation to accept or reject.
- *
- * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public boolean acceptInvite(Message inviteMessage) throws JMSException
- {
- log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
-
- // All invites are acceptable.
- return true;
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the
- * assignment message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- *
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
- + "): called");
-
- // Reset the message count for a new test.
- messageCount = 0;
-
- // Take note of the role to be played.
- this.role = role;
-
- // Create a new connection to pass the test messages on.
- connection = TestUtils.createConnection(TestClient.testContextProperties);
- session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Extract and retain the test parameters.
- numMessages = assignRoleMessage.getIntProperty("P2P_NUM_MESSAGES");
- Destination sendDestination = session.createQueue(assignRoleMessage.getStringProperty("P2P_QUEUE_AND_KEY_NAME"));
-
- log.debug("numMessages = " + numMessages);
- log.debug("sendDestination = " + sendDestination);
- log.debug("role = " + role);
-
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a message producer if so.
- case SENDER:
- producer = session.createProducer(sendDestination);
- break;
-
- // Otherwise the receivers role is being assigned, so set this up to listen for messages.
- case RECEIVER:
- MessageConsumer consumer = session.createConsumer(sendDestination);
- consumer.setMessageListener(this);
- break;
- }
-
- connection.start();
- }
-
- /**
- * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
- *
- * @param numMessages The number of test messages to send.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void start(int numMessages) throws JMSException
- {
- log.debug("public void start(): called");
-
- // Check that the sender role is being performed.
- if (role.equals(Roles.SENDER))
- {
- Message testMessage = session.createTextMessage("test");
-
- for (int i = 0; i < this.numMessages; i++)
- {
- producer.send(testMessage);
-
- // Increment the message count.
- messageCount++;
- }
- }
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Close the test connection.
- connection.close();
-
- // Generate a report message containing the count of the number of messages passed.
- Message report = session.createMessage();
- report.setStringProperty("CONTROL_TYPE", "REPORT");
- report.setIntProperty("MESSAGE_COUNT", messageCount);
-
- return report;
- }
-
- /**
- * Counts incoming test messages.
- *
- * @param message The incoming test message.
- */
- public void onMessage(Message message)
- {
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- // Increment the message count.
- messageCount++;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.clienttestcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.distributedtesting.TestClient;
+import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
+
+import javax.jms.*;
+
+/**
+ * Implements test case 2, basic P2P. Sends/received a specified number of messages to a specified route on the
+ * default direct exchange. Produces reports on the actual number of messages sent/received.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Send required number of test messages.
+ * <tr><td> Generate test reports.
+ * </table>
+ */
+public class TestCase2BasicP2P implements TestClientControlledTest, MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestCase2BasicP2P.class);
+
+ /** Holds the count of test messages received. */
+ private int messageCount;
+
+ /** The role to be played by the test. */
+ private Roles role;
+
+ /** The number of test messages to send. */
+ private int numMessages;
+
+ /** The connection to send the test messages on. */
+ private Connection connection;
+
+ /** The controlSession to send the test messages on. */
+ private Session session;
+
+ /** The producer to send the test messages with. */
+ MessageProducer producer;
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the
+ * interop testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "TC2_BasicP2P";
+ }
+
+ /**
+ * Determines whether the test invite that matched this test case is acceptable.
+ *
+ * @param inviteMessage The invitation to accept or reject.
+ *
+ * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public boolean acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the
+ * assignment message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ *
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Create a new connection to pass the test messages on.
+ connection = TestUtils.createConnection(TestClient.testContextProperties);
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.getIntProperty("P2P_NUM_MESSAGES");
+ Destination sendDestination = session.createQueue(assignRoleMessage.getStringProperty("P2P_QUEUE_AND_KEY_NAME"));
+
+ log.debug("numMessages = " + numMessages);
+ log.debug("sendDestination = " + sendDestination);
+ log.debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a message producer if so.
+ case SENDER:
+ producer = session.createProducer(sendDestination);
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages.
+ case RECEIVER:
+ MessageConsumer consumer = session.createConsumer(sendDestination);
+ consumer.setMessageListener(this);
+ break;
+ }
+
+ connection.start();
+ }
+
+ /**
+ * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ *
+ * @param numMessages The number of test messages to send.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = session.createTextMessage("test");
+
+ for (int i = 0; i < this.numMessages; i++)
+ {
+ producer.send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Close the test connection.
+ connection.close();
+
+ // Generate a report message containing the count of the number of messages passed.
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+ report.setIntProperty("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /**
+ * Counts incoming test messages.
+ *
+ * @param message The incoming test message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java
index 622ddc2f64..205472716b 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase3BasicPubSub.java
@@ -1,239 +1,239 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.clienttestcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.distributedtesting.TestClient;
-import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-
-import javax.jms.*;
-
-/**
- * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
- * messages sent/received.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Send required number of test messages using pub/sub.
- * <tr><td> Generate test reports.
- * </table>
- */
-public class TestCase3BasicPubSub implements TestClientControlledTest, MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestCase3BasicPubSub.class);
-
- /** Holds the count of test messages received. */
- private int messageCount;
-
- /** The role to be played by the test. */
- private Roles role;
-
- /** The number of test messages to send. */
- private int numMessages;
-
- /** The connections to send/receive the test messages on. */
- private Connection[] connection;
-
- /** The sessions to send/receive the test messages on. */
- private Session[] session;
-
- /** The producer to send the test messages with. */
- MessageProducer producer;
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the
- * interop testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "TC3_BasicPubSub";
- }
-
- /**
- * Determines whether the test invite that matched this test case is acceptable.
- *
- * @param inviteMessage The invitation to accept or reject.
- *
- * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
- *
- * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public boolean acceptInvite(Message inviteMessage) throws JMSException
- {
- log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
-
- // All invites are acceptable.
- return true;
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the
- * assignment message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- *
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
- + "): called");
-
- // Reset the message count for a new test.
- messageCount = 0;
-
- // Take note of the role to be played.
- this.role = role;
-
- // Extract and retain the test parameters.
- numMessages = assignRoleMessage.getIntProperty("PUBSUB_NUM_MESSAGES");
- int numReceivers = assignRoleMessage.getIntProperty("PUBSUB_NUM_RECEIVERS");
- String sendKey = assignRoleMessage.getStringProperty("PUBSUB_KEY");
-
- log.debug("numMessages = " + numMessages);
- log.debug("numReceivers = " + numReceivers);
- log.debug("sendKey = " + sendKey);
- log.debug("role = " + role);
-
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a single message producer if so.
- case SENDER:
- // Create a new connection to pass the test messages on.
- connection = new Connection[1];
- session = new Session[1];
-
- connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
- session[0] = connection[0].createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Extract and retain the test parameters.
- Destination sendDestination = session[0].createTopic(sendKey);
-
- producer = session[0].createProducer(sendDestination);
- break;
-
- // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
- // of receivers connections.
- case RECEIVER:
- // Create the required number of receivers connections.
- connection = new Connection[numReceivers];
- session = new Session[numReceivers];
-
- for (int i = 0; i < numReceivers; i++)
- {
- connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
- session[i] = connection[i].createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- sendDestination = session[i].createTopic(sendKey);
-
- MessageConsumer consumer = session[i].createConsumer(sendDestination);
- consumer.setMessageListener(this);
- }
-
- break;
- }
-
- // Start all the connection dispatcher threads running.
- for (Connection conn : connection)
- {
- conn.start();
- }
- }
-
- /**
- * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
- *
- * @param numMessages The number of test messages to send.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void start(int numMessages) throws JMSException
- {
- log.debug("public void start(): called");
-
- // Check that the sender role is being performed.
- if (role.equals(Roles.SENDER))
- {
- Message testMessage = session[0].createTextMessage("test");
-
- for (int i = 0; i < this.numMessages; i++)
- {
- producer.send(testMessage);
-
- // Increment the message count.
- messageCount++;
- }
- }
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Close the test connections.
- for (Connection conn : connection)
- {
- conn.close();
- }
-
- // Generate a report message containing the count of the number of messages passed.
- Message report = session.createMessage();
- report.setStringProperty("CONTROL_TYPE", "REPORT");
- report.setIntProperty("MESSAGE_COUNT", messageCount);
-
- return report;
- }
-
- /**
- * Counts incoming test messages.
- *
- * @param message The incoming test message.
- */
- public void onMessage(Message message)
- {
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- // Increment the message count.
- messageCount++;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.clienttestcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.distributedtesting.TestClient;
+import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
+
+import javax.jms.*;
+
+/**
+ * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
+ * messages sent/received.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Send required number of test messages using pub/sub.
+ * <tr><td> Generate test reports.
+ * </table>
+ */
+public class TestCase3BasicPubSub implements TestClientControlledTest, MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestCase3BasicPubSub.class);
+
+ /** Holds the count of test messages received. */
+ private int messageCount;
+
+ /** The role to be played by the test. */
+ private Roles role;
+
+ /** The number of test messages to send. */
+ private int numMessages;
+
+ /** The connections to send/receive the test messages on. */
+ private Connection[] connection;
+
+ /** The sessions to send/receive the test messages on. */
+ private Session[] session;
+
+ /** The producer to send the test messages with. */
+ MessageProducer producer;
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the
+ * interop testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "TC3_BasicPubSub";
+ }
+
+ /**
+ * Determines whether the test invite that matched this test case is acceptable.
+ *
+ * @param inviteMessage The invitation to accept or reject.
+ *
+ * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
+ *
+ * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public boolean acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the
+ * assignment message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ *
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.getIntProperty("PUBSUB_NUM_MESSAGES");
+ int numReceivers = assignRoleMessage.getIntProperty("PUBSUB_NUM_RECEIVERS");
+ String sendKey = assignRoleMessage.getStringProperty("PUBSUB_KEY");
+
+ log.debug("numMessages = " + numMessages);
+ log.debug("numReceivers = " + numReceivers);
+ log.debug("sendKey = " + sendKey);
+ log.debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new Connection[1];
+ session = new Session[1];
+
+ connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[0] = connection[0].createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Extract and retain the test parameters.
+ Destination sendDestination = session[0].createTopic(sendKey);
+
+ producer = session[0].createProducer(sendDestination);
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+ // of receivers connections.
+ case RECEIVER:
+ // Create the required number of receivers connections.
+ connection = new Connection[numReceivers];
+ session = new Session[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[i] = connection[i].createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ sendDestination = session[i].createTopic(sendKey);
+
+ MessageConsumer consumer = session[i].createConsumer(sendDestination);
+ consumer.setMessageListener(this);
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ for (Connection conn : connection)
+ {
+ conn.start();
+ }
+ }
+
+ /**
+ * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ *
+ * @param numMessages The number of test messages to send.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = session[0].createTextMessage("test");
+
+ for (int i = 0; i < this.numMessages; i++)
+ {
+ producer.send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Close the test connections.
+ for (Connection conn : connection)
+ {
+ conn.close();
+ }
+
+ // Generate a report message containing the count of the number of messages passed.
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+ report.setIntProperty("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /**
+ * Counts incoming test messages.
+ *
+ * @param message The incoming test message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java
index 0388c56678..3730233264 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase4P2PMessageSize.java
@@ -1,214 +1,214 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.clienttestcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.distributedtesting.TestClient;
-import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-
-import javax.jms.*;
-
-/**
- * Implements test case 4, P2P messages with message size. Sends/received a specified number of messages to a specified
- * route on the default direct exchange, of a specified size. Produces reports on the actual number of messages
- * sent/received.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Send required number of test messages.
- * <tr><td> Generate test reports.
- * </table>
- */
-public class TestCase4P2PMessageSize implements TestClientControlledTest, MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestCase4P2PMessageSize.class);
-
- /** Holds the count of test messages received. */
- private int messageCount;
-
- /** The role to be played by the test. */
- private Roles role;
-
- /** The number of test messages to send. */
- private int numMessages;
-
- /** The size of the test messages to send. */
- private int messageSize;
-
- /** The connection to send the test messages on. */
- private Connection connection;
-
- /** The controlSession to send the test messages on. */
- private Session session;
-
- /** The producer to send the test messages with. */
- MessageProducer producer;
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the
- * interop testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "TC4_P2PMessageSize";
- }
-
- /**
- * Determines whether the test invite that matched this test case is acceptable.
- *
- * @param inviteMessage The invitation to accept or reject.
- *
- * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public boolean acceptInvite(Message inviteMessage) throws JMSException
- {
- log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
-
- // All invites are acceptable.
- return true;
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the
- * assignment message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- *
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
- + "): called");
-
- // Reset the message count for a new test.
- messageCount = 0;
-
- // Take note of the role to be played.
- this.role = role;
-
- // Create a new connection to pass the test messages on.
- connection = TestUtils.createConnection(TestClient.testContextProperties);
- session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Extract and retain the test parameters.
- numMessages = assignRoleMessage.getIntProperty("P2P_NUM_MESSAGES");
- messageSize = assignRoleMessage.getIntProperty("messageSize");
- Destination sendDestination = session.createQueue(assignRoleMessage.getStringProperty("P2P_QUEUE_AND_KEY_NAME"));
-
- log.debug("numMessages = " + numMessages);
- log.debug("sendDestination = " + sendDestination);
- log.debug("role = " + role);
-
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a message producer if so.
- case SENDER:
- producer = session.createProducer(sendDestination);
- break;
-
- // Otherwise the receivers role is being assigned, so set this up to listen for messages.
- case RECEIVER:
- MessageConsumer consumer = session.createConsumer(sendDestination);
- consumer.setMessageListener(this);
- break;
- }
-
- connection.start();
- }
-
- /**
- * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
- *
- * @param numMessages The number of test messages to send.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void start(int numMessages) throws JMSException
- {
- log.debug("public void start(): called");
-
- // Check that the sender role is being performed.
- if (role.equals(Roles.SENDER))
- {
- Message testMessage = TestUtils.createTestMessageOfSize(session, messageSize);
-
- for (int i = 0; i < this.numMessages; i++)
- {
- producer.send(testMessage);
-
- // Increment the message count.
- messageCount++;
- }
- }
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Close the test connection.
- connection.close();
-
- // Generate a report message containing the count of the number of messages passed.
- Message report = session.createMessage();
- report.setStringProperty("CONTROL_TYPE", "REPORT");
- report.setIntProperty("MESSAGE_COUNT", messageCount);
-
- return report;
- }
-
- /**
- * Counts incoming test messages.
- *
- * @param message The incoming test message.
- */
- public void onMessage(Message message)
- {
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- // Increment the message count.
- messageCount++;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.clienttestcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.distributedtesting.TestClient;
+import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
+
+import javax.jms.*;
+
+/**
+ * Implements test case 4, P2P messages with message size. Sends/received a specified number of messages to a specified
+ * route on the default direct exchange, of a specified size. Produces reports on the actual number of messages
+ * sent/received.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Send required number of test messages.
+ * <tr><td> Generate test reports.
+ * </table>
+ */
+public class TestCase4P2PMessageSize implements TestClientControlledTest, MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestCase4P2PMessageSize.class);
+
+ /** Holds the count of test messages received. */
+ private int messageCount;
+
+ /** The role to be played by the test. */
+ private Roles role;
+
+ /** The number of test messages to send. */
+ private int numMessages;
+
+ /** The size of the test messages to send. */
+ private int messageSize;
+
+ /** The connection to send the test messages on. */
+ private Connection connection;
+
+ /** The controlSession to send the test messages on. */
+ private Session session;
+
+ /** The producer to send the test messages with. */
+ MessageProducer producer;
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the
+ * interop testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "TC4_P2PMessageSize";
+ }
+
+ /**
+ * Determines whether the test invite that matched this test case is acceptable.
+ *
+ * @param inviteMessage The invitation to accept or reject.
+ *
+ * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public boolean acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the
+ * assignment message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ *
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Create a new connection to pass the test messages on.
+ connection = TestUtils.createConnection(TestClient.testContextProperties);
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.getIntProperty("P2P_NUM_MESSAGES");
+ messageSize = assignRoleMessage.getIntProperty("messageSize");
+ Destination sendDestination = session.createQueue(assignRoleMessage.getStringProperty("P2P_QUEUE_AND_KEY_NAME"));
+
+ log.debug("numMessages = " + numMessages);
+ log.debug("sendDestination = " + sendDestination);
+ log.debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a message producer if so.
+ case SENDER:
+ producer = session.createProducer(sendDestination);
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages.
+ case RECEIVER:
+ MessageConsumer consumer = session.createConsumer(sendDestination);
+ consumer.setMessageListener(this);
+ break;
+ }
+
+ connection.start();
+ }
+
+ /**
+ * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ *
+ * @param numMessages The number of test messages to send.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = TestUtils.createTestMessageOfSize(session, messageSize);
+
+ for (int i = 0; i < this.numMessages; i++)
+ {
+ producer.send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Close the test connection.
+ connection.close();
+
+ // Generate a report message containing the count of the number of messages passed.
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+ report.setIntProperty("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /**
+ * Counts incoming test messages.
+ *
+ * @param message The incoming test message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java
index ab59e16ab3..f601712bc9 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/clienttestcases/TestCase5PubSubMessageSize.java
@@ -1,243 +1,243 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.clienttestcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.distributedtesting.TestClient;
-import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
-
-import javax.jms.*;
-
-/**
- * Implements test case 5, pub/sub with message size. Sends/received a specified number of messages to a specified route
- * on the default topic exchange, using the specified number of receivers connections, and the specified message size.
- * Produces reports on the actual number of messages sent/received.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Send required number of test messages using pub/sub.
- * <tr><td> Generate test reports.
- * </table>
- */
-public class TestCase5PubSubMessageSize implements TestClientControlledTest, MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestCase5PubSubMessageSize.class);
-
- /** Holds the count of test messages received. */
- private int messageCount;
-
- /** The role to be played by the test. */
- private Roles role;
-
- /** The number of test messages to send. */
- private int numMessages;
-
- /** The size of the test messages to send. */
- private int messageSize;
-
- /** The connections to send/receive the test messages on. */
- private Connection[] connection;
-
- /** The sessions to send/receive the test messages on. */
- private Session[] session;
-
- /** The producer to send the test messages with. */
- MessageProducer producer;
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the
- * interop testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "TC5_PubSubMessageSize";
- }
-
- /**
- * Determines whether the test invite that matched this test case is acceptable.
- *
- * @param inviteMessage The invitation to accept or reject.
- *
- * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
- *
- * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public boolean acceptInvite(Message inviteMessage) throws JMSException
- {
- log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
-
- // All invites are acceptable.
- return true;
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the
- * assignment message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- *
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
- + "): called");
-
- // Reset the message count for a new test.
- messageCount = 0;
-
- // Take note of the role to be played.
- this.role = role;
-
- // Extract and retain the test parameters.
- numMessages = assignRoleMessage.getIntProperty("PUBSUB_NUM_MESSAGES");
- messageSize = assignRoleMessage.getIntProperty("messageSize");
- int numReceivers = assignRoleMessage.getIntProperty("PUBSUB_NUM_RECEIVERS");
- String sendKey = assignRoleMessage.getStringProperty("PUBSUB_KEY");
-
- log.debug("numMessages = " + numMessages);
- log.debug("numReceivers = " + numReceivers);
- log.debug("sendKey = " + sendKey);
- log.debug("role = " + role);
-
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a single message producer if so.
- case SENDER:
- // Create a new connection to pass the test messages on.
- connection = new Connection[1];
- session = new Session[1];
-
- connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
- session[0] = connection[0].createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Extract and retain the test parameters.
- Destination sendDestination = session[0].createTopic(sendKey);
-
- producer = session[0].createProducer(sendDestination);
- break;
-
- // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
- // of receivers connections.
- case RECEIVER:
- // Create the required number of receivers connections.
- connection = new Connection[numReceivers];
- session = new Session[numReceivers];
-
- for (int i = 0; i < numReceivers; i++)
- {
- connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
- session[i] = connection[i].createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- sendDestination = session[i].createTopic(sendKey);
-
- MessageConsumer consumer = session[i].createConsumer(sendDestination);
- consumer.setMessageListener(this);
- }
-
- break;
- }
-
- // Start all the connection dispatcher threads running.
- for (Connection conn : connection)
- {
- conn.start();
- }
- }
-
- /**
- * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
- *
- * @param numMessages The number of test messages to send.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void start(int numMessages) throws JMSException
- {
- log.debug("public void start(): called");
-
- // Check that the sender role is being performed.
- if (role.equals(Roles.SENDER))
- {
- Message testMessage = TestUtils.createTestMessageOfSize(session[0], messageSize);
-
- for (int i = 0; i < this.numMessages; i++)
- {
- producer.send(testMessage);
-
- // Increment the message count.
- messageCount++;
- }
- }
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws javax.jms.JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Close the test connections.
- for (Connection conn : connection)
- {
- conn.close();
- }
-
- // Generate a report message containing the count of the number of messages passed.
- Message report = session.createMessage();
- report.setStringProperty("CONTROL_TYPE", "REPORT");
- report.setIntProperty("MESSAGE_COUNT", messageCount);
-
- return report;
- }
-
- /**
- * Counts incoming test messages.
- *
- * @param message The incoming test message.
- */
- public void onMessage(Message message)
- {
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- // Increment the message count.
- messageCount++;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.clienttestcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.distributedtesting.TestClient;
+import org.apache.qpid.test.framework.distributedtesting.TestClientControlledTest;
+
+import javax.jms.*;
+
+/**
+ * Implements test case 5, pub/sub with message size. Sends/received a specified number of messages to a specified route
+ * on the default topic exchange, using the specified number of receivers connections, and the specified message size.
+ * Produces reports on the actual number of messages sent/received.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Send required number of test messages using pub/sub.
+ * <tr><td> Generate test reports.
+ * </table>
+ */
+public class TestCase5PubSubMessageSize implements TestClientControlledTest, MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestCase5PubSubMessageSize.class);
+
+ /** Holds the count of test messages received. */
+ private int messageCount;
+
+ /** The role to be played by the test. */
+ private Roles role;
+
+ /** The number of test messages to send. */
+ private int numMessages;
+
+ /** The size of the test messages to send. */
+ private int messageSize;
+
+ /** The connections to send/receive the test messages on. */
+ private Connection[] connection;
+
+ /** The sessions to send/receive the test messages on. */
+ private Session[] session;
+
+ /** The producer to send the test messages with. */
+ MessageProducer producer;
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the
+ * interop testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "TC5_PubSubMessageSize";
+ }
+
+ /**
+ * Determines whether the test invite that matched this test case is acceptable.
+ *
+ * @param inviteMessage The invitation to accept or reject.
+ *
+ * @return <tt>true</tt> to accept the invitation, <tt>false</tt> to reject it.
+ *
+ * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public boolean acceptInvite(Message inviteMessage) throws JMSException
+ {
+ log.debug("public boolean acceptInvite(Message inviteMessage = " + inviteMessage + "): called");
+
+ // All invites are acceptable.
+ return true;
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the
+ * assignment message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ *
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws javax.jms.JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Reset the message count for a new test.
+ messageCount = 0;
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numMessages = assignRoleMessage.getIntProperty("PUBSUB_NUM_MESSAGES");
+ messageSize = assignRoleMessage.getIntProperty("messageSize");
+ int numReceivers = assignRoleMessage.getIntProperty("PUBSUB_NUM_RECEIVERS");
+ String sendKey = assignRoleMessage.getStringProperty("PUBSUB_KEY");
+
+ log.debug("numMessages = " + numMessages);
+ log.debug("numReceivers = " + numReceivers);
+ log.debug("sendKey = " + sendKey);
+ log.debug("role = " + role);
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case SENDER:
+ // Create a new connection to pass the test messages on.
+ connection = new Connection[1];
+ session = new Session[1];
+
+ connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[0] = connection[0].createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Extract and retain the test parameters.
+ Destination sendDestination = session[0].createTopic(sendKey);
+
+ producer = session[0].createProducer(sendDestination);
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+ // of receivers connections.
+ case RECEIVER:
+ // Create the required number of receivers connections.
+ connection = new Connection[numReceivers];
+ session = new Session[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[i] = connection[i].createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ sendDestination = session[i].createTopic(sendKey);
+
+ MessageConsumer consumer = session[i].createConsumer(sendDestination);
+ consumer.setMessageListener(this);
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ for (Connection conn : connection)
+ {
+ conn.start();
+ }
+ }
+
+ /**
+ * Performs the test case actions. Returning from here, indicates that the sending role has completed its test.
+ *
+ * @param numMessages The number of test messages to send.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ if (role.equals(Roles.SENDER))
+ {
+ Message testMessage = TestUtils.createTestMessageOfSize(session[0], messageSize);
+
+ for (int i = 0; i < this.numMessages; i++)
+ {
+ producer.send(testMessage);
+
+ // Increment the message count.
+ messageCount++;
+ }
+ }
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws javax.jms.JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Close the test connections.
+ for (Connection conn : connection)
+ {
+ conn.close();
+ }
+
+ // Generate a report message containing the count of the number of messages passed.
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+ report.setIntProperty("MESSAGE_COUNT", messageCount);
+
+ return report;
+ }
+
+ /**
+ * Counts incoming test messages.
+ *
+ * @param message The incoming test message.
+ */
+ public void onMessage(Message message)
+ {
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ // Increment the message count.
+ messageCount++;
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java
index 60cd9f47f3..a2e4a00aa6 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase1DummyRun.java
@@ -1,84 +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.interop.testcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import java.util.Properties;
-
-/**
- * Coordinates test case 1, from the interop test specification. This test connects up the sender and receivers roles,
- * and gets some dummy test reports from them, in order to check that the test framework itself is operational.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Exercises the interop testing framework without actually sending any test messages.
- * <td> {@link FrameworkBaseCase}
- * </table>
- */
-public class InteropTestCase1DummyRun extends FrameworkBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase1DummyRun.class);
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase1DummyRun(String name)
- {
- super(name);
- }
-
- /**
- * Performs the basic P2P test case, "Test Case 2" in the specification.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testDummyRun() throws Exception
- {
- log.debug("public void testDummyRun(): called");
-
- Properties testConfig = new Properties();
- testConfig.put("TEST_NAME", "TC1_DummyRun");
-
- /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
-
- // Compare sender and receivers reports.
- // Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as defined in the
- * interop testing specification. For example the method "testP2P" might map onto the interop test case name
- * "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "TC1_DummyRun";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import java.util.Properties;
+
+/**
+ * Coordinates test case 1, from the interop test specification. This test connects up the sender and receivers roles,
+ * and gets some dummy test reports from them, in order to check that the test framework itself is operational.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Exercises the interop testing framework without actually sending any test messages.
+ * <td> {@link FrameworkBaseCase}
+ * </table>
+ */
+public class InteropTestCase1DummyRun extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(InteropTestCase1DummyRun.class);
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public InteropTestCase1DummyRun(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the basic P2P test case, "Test Case 2" in the specification.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testDummyRun() throws Exception
+ {
+ log.debug("public void testDummyRun(): called");
+
+ Properties testConfig = new Properties();
+ testConfig.put("TEST_NAME", "TC1_DummyRun");
+
+ /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
+
+ // Compare sender and receivers reports.
+ // Assert.assertEquals("Expected to get 2 dummy reports.", 2, reports.length);
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as defined in the
+ * interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ * "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "TC1_DummyRun";
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java
index 8983249daa..6d6515f1fd 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase2BasicP2P.java
@@ -1,90 +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.
- *
- */
-package org.apache.qpid.interop.testcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import java.util.Properties;
-
-/**
- * Implements test case 2, from the interop test specification. This test sets up the TC2_BasicP2P test for 50
- * messages. It checks that the sender and receivers reports both indicate that all the test messages were transmitted
- * successfully.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
- * </table>
- */
-public class InteropTestCase2BasicP2P extends FrameworkBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase2BasicP2P.class);
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase2BasicP2P(String name)
- {
- super(name);
- }
-
- /**
- * Performs the basic P2P test case, "Test Case 2" in the specification.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testBasicP2P() throws Exception
- {
- log.debug("public void testBasicP2P(): called");
-
- Properties testConfig = new Properties();
- testConfig.setProperty("TEST_NAME", "TC2_BasicP2P");
- testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
- testConfig.put("P2P_NUM_MESSAGES", 50);
-
- /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
-
- // Compare sender and receivers reports.
- /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
- int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
-
- Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
- Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);*/
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as defined in the
- * interop testing specification. For example the method "testP2P" might map onto the interop test case name
- * "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "TC2_BasicP2P";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import java.util.Properties;
+
+/**
+ * Implements test case 2, from the interop test specification. This test sets up the TC2_BasicP2P test for 50
+ * messages. It checks that the sender and receivers reports both indicate that all the test messages were transmitted
+ * successfully.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ * </table>
+ */
+public class InteropTestCase2BasicP2P extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(InteropTestCase2BasicP2P.class);
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public InteropTestCase2BasicP2P(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the basic P2P test case, "Test Case 2" in the specification.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testBasicP2P() throws Exception
+ {
+ log.debug("public void testBasicP2P(): called");
+
+ Properties testConfig = new Properties();
+ testConfig.setProperty("TEST_NAME", "TC2_BasicP2P");
+ testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
+ testConfig.put("P2P_NUM_MESSAGES", 50);
+
+ /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
+
+ // Compare sender and receivers reports.
+ /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
+
+ Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
+ Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);*/
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as defined in the
+ * interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ * "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "TC2_BasicP2P";
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java
index 6e87c3e3ee..2faca91e73 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase3BasicPubSub.java
@@ -1,88 +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.interop.testcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import java.util.Properties;
-
-/**
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link FrameworkBaseCase}
- * </table>
- */
-public class InteropTestCase3BasicPubSub extends FrameworkBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase3BasicPubSub.class);
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase3BasicPubSub(String name)
- {
- super(name);
- }
-
- /**
- * Performs the basic P2P test case, "Test Case 2" in the specification.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testBasicPubSub() throws Exception
- {
- log.debug("public void testBasicPubSub(): called");
-
- Properties testConfig = new Properties();
- testConfig.put("TEST_NAME", "TC3_BasicPubSub");
- testConfig.put("PUBSUB_KEY", "tc3route");
- testConfig.put("PUBSUB_NUM_MESSAGES", 10);
- testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
-
- /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
-
- // Compare sender and receivers reports.
- /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
- int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
-
- Assert.assertEquals("The requested number of messages were not sent.", 10, messagesSent);
- Assert.assertEquals("Received messages did not match up to num sent * num receivers.", messagesSent * 5,
- messagesReceived);*/
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as defined in the
- * interop testing specification. For example the method "testP2P" might map onto the interop test case name
- * "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "TC3_BasicPubSub";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import java.util.Properties;
+
+/**
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ * </table>
+ */
+public class InteropTestCase3BasicPubSub extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(InteropTestCase3BasicPubSub.class);
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public InteropTestCase3BasicPubSub(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the basic P2P test case, "Test Case 2" in the specification.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testBasicPubSub() throws Exception
+ {
+ log.debug("public void testBasicPubSub(): called");
+
+ Properties testConfig = new Properties();
+ testConfig.put("TEST_NAME", "TC3_BasicPubSub");
+ testConfig.put("PUBSUB_KEY", "tc3route");
+ testConfig.put("PUBSUB_NUM_MESSAGES", 10);
+ testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
+
+ /*Message[] reports =*/ getCircuitFactory().sequenceTest(null, null, testConfig);
+
+ // Compare sender and receivers reports.
+ /*int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
+
+ Assert.assertEquals("The requested number of messages were not sent.", 10, messagesSent);
+ Assert.assertEquals("Received messages did not match up to num sent * num receivers.", messagesSent * 5,
+ messagesReceived);*/
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as defined in the
+ * interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ * "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "TC3_BasicPubSub";
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java
index c3f450ec42..2d64f2b805 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase4P2PMessageSize.java
@@ -1,193 +1,193 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.testcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import java.util.Properties;
-
-/**
- * Implements test case 4, from the interop test specification. This test sets up the TC2_P2PMessageSize test for 50
- * messages, and a variety of message sizes. It checks that the sender and receivers reports both indicate that all
- * the test messages were transmitted successfully.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
- * </table>
- */
-public class InteropTestCase4P2PMessageSize extends FrameworkBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase4P2PMessageSize.class);
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase4P2PMessageSize(String name)
- {
- super(name);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 0K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize0K() throws Exception
- {
- runTestForMessagesOfSize(0);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 63K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize63K() throws Exception
- {
- runTestForMessagesOfSize(63 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 64K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize64K() throws Exception
- {
- runTestForMessagesOfSize(64 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 65K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize65K() throws Exception
- {
- runTestForMessagesOfSize(65 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 127K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize127K() throws Exception
- {
- runTestForMessagesOfSize(127 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 128K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize128K() throws Exception
- {
- runTestForMessagesOfSize(128 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 129K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize129K() throws Exception
- {
- runTestForMessagesOfSize(129 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 255K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize255K() throws Exception
- {
- runTestForMessagesOfSize(255 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 256K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize256K() throws Exception
- {
- runTestForMessagesOfSize(256 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 257K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testP2PMessageSize257K() throws Exception
- {
- runTestForMessagesOfSize(257 * 1024);
- }
-
- /**
- * Sends 50 test messages of the specified size, and asserts that all were received.
- *
- * @param size The size of the messages to send in bytes.
- */
- private void runTestForMessagesOfSize(int size)
- {
- Properties testConfig = new Properties();
- testConfig.setProperty("TEST_NAME", "TC4_P2PMessageSize");
- testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
- testConfig.put("P2P_NUM_MESSAGES", 50);
- testConfig.put("messageSize", size);
-
- /*Message[] reports =*/
- getCircuitFactory().sequenceTest(null, null, testConfig);
-
- // Compare sender and receivers reports.
- /*
- int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
- int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
-
- Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
- Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);
- */
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as defined in the
- * interop testing specification. For example the method "testP2P" might map onto the interop test case name
- * "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- *
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "TC4_P2PMessageSize";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import java.util.Properties;
+
+/**
+ * Implements test case 4, from the interop test specification. This test sets up the TC2_P2PMessageSize test for 50
+ * messages, and a variety of message sizes. It checks that the sender and receivers reports both indicate that all
+ * the test messages were transmitted successfully.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup p2p test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ * </table>
+ */
+public class InteropTestCase4P2PMessageSize extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(InteropTestCase4P2PMessageSize.class);
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public InteropTestCase4P2PMessageSize(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 0K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize0K() throws Exception
+ {
+ runTestForMessagesOfSize(0);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 63K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize63K() throws Exception
+ {
+ runTestForMessagesOfSize(63 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 64K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize64K() throws Exception
+ {
+ runTestForMessagesOfSize(64 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 65K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize65K() throws Exception
+ {
+ runTestForMessagesOfSize(65 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 127K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize127K() throws Exception
+ {
+ runTestForMessagesOfSize(127 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 128K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize128K() throws Exception
+ {
+ runTestForMessagesOfSize(128 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 129K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize129K() throws Exception
+ {
+ runTestForMessagesOfSize(129 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 255K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize255K() throws Exception
+ {
+ runTestForMessagesOfSize(255 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 256K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize256K() throws Exception
+ {
+ runTestForMessagesOfSize(256 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 257K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testP2PMessageSize257K() throws Exception
+ {
+ runTestForMessagesOfSize(257 * 1024);
+ }
+
+ /**
+ * Sends 50 test messages of the specified size, and asserts that all were received.
+ *
+ * @param size The size of the messages to send in bytes.
+ */
+ private void runTestForMessagesOfSize(int size)
+ {
+ Properties testConfig = new Properties();
+ testConfig.setProperty("TEST_NAME", "TC4_P2PMessageSize");
+ testConfig.setProperty("P2P_QUEUE_AND_KEY_NAME", "tc2queue");
+ testConfig.put("P2P_NUM_MESSAGES", 50);
+ testConfig.put("messageSize", size);
+
+ /*Message[] reports =*/
+ getCircuitFactory().sequenceTest(null, null, testConfig);
+
+ // Compare sender and receivers reports.
+ /*
+ int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
+
+ Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
+ Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);
+ */
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as defined in the
+ * interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ * "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "TC4_P2PMessageSize";
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java
index 86a0a60ea4..23d33fc115 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/interop/testcases/InteropTestCase5PubSubMessageSize.java
@@ -1,193 +1,193 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.interop.testcases;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import java.util.Properties;
-
-/**
- * Implements test case 5, from the interop test specification. This test sets up the TC2_PubSubMessageSize test for 10
- * messages, sent to 5 consumers, and a variety of message sizes. It checks that the sender and receivers reports both
- * indicate that all the test messages were transmitted successfully.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link FrameworkBaseCase}
- * </table>
- */
-public class InteropTestCase5PubSubMessageSize extends FrameworkBaseCase
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(InteropTestCase5PubSubMessageSize.class);
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public InteropTestCase5PubSubMessageSize(String name)
- {
- super(name);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 0K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize0K() throws Exception
- {
- runTestForMessagesOfSize(0);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 63K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize63K() throws Exception
- {
- runTestForMessagesOfSize(63 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 64K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize64K() throws Exception
- {
- runTestForMessagesOfSize(64 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 65K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize65K() throws Exception
- {
- runTestForMessagesOfSize(65 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 127K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize127K() throws Exception
- {
- runTestForMessagesOfSize(127 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 128K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize128K() throws Exception
- {
- runTestForMessagesOfSize(128 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 129K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize129K() throws Exception
- {
- runTestForMessagesOfSize(129 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 255K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize255K() throws Exception
- {
- runTestForMessagesOfSize(255 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 256K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize256K() throws Exception
- {
- runTestForMessagesOfSize(256 * 1024);
- }
-
- /**
- * Performs the P2P message test case, "Test Case 4" in the specification, for messages 257K in size.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testPubSubMessageSize257K() throws Exception
- {
- runTestForMessagesOfSize(257 * 1024);
- }
-
- /**
- * Sends 50 test messages of the specified size, and asserts that all were received.
- *
- * @param size The size of the messages to send in bytes.
- */
- private void runTestForMessagesOfSize(int size)
- {
- Properties testConfig = new Properties();
- testConfig.put("TEST_NAME", "TC5_PubSubMessageSize");
- testConfig.put("PUBSUB_KEY", "tc3route");
- testConfig.put("PUBSUB_NUM_MESSAGES", 10);
- testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
- testConfig.put("messageSize", size);
-
- /*Message[] reports =*/
- getCircuitFactory().sequenceTest(null, null, testConfig);
-
- // Compare sender and receivers reports.
- /*
- int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
- int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
-
- Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
- Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);
- */
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as defined in the
- * interop testing specification. For example the method "testP2P" might map onto the interop test case name
- * "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "TC5_PubSubMessageSize";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.interop.testcases;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import java.util.Properties;
+
+/**
+ * Implements test case 5, from the interop test specification. This test sets up the TC2_PubSubMessageSize test for 10
+ * messages, sent to 5 consumers, and a variety of message sizes. It checks that the sender and receivers reports both
+ * indicate that all the test messages were transmitted successfully.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup pub/sub test parameters and compare with test output. <td> {@link FrameworkBaseCase}
+ * </table>
+ */
+public class InteropTestCase5PubSubMessageSize extends FrameworkBaseCase
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(InteropTestCase5PubSubMessageSize.class);
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public InteropTestCase5PubSubMessageSize(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 0K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize0K() throws Exception
+ {
+ runTestForMessagesOfSize(0);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 63K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize63K() throws Exception
+ {
+ runTestForMessagesOfSize(63 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 64K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize64K() throws Exception
+ {
+ runTestForMessagesOfSize(64 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 65K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize65K() throws Exception
+ {
+ runTestForMessagesOfSize(65 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 127K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize127K() throws Exception
+ {
+ runTestForMessagesOfSize(127 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 128K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize128K() throws Exception
+ {
+ runTestForMessagesOfSize(128 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 129K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize129K() throws Exception
+ {
+ runTestForMessagesOfSize(129 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 255K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize255K() throws Exception
+ {
+ runTestForMessagesOfSize(255 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 256K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize256K() throws Exception
+ {
+ runTestForMessagesOfSize(256 * 1024);
+ }
+
+ /**
+ * Performs the P2P message test case, "Test Case 4" in the specification, for messages 257K in size.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testPubSubMessageSize257K() throws Exception
+ {
+ runTestForMessagesOfSize(257 * 1024);
+ }
+
+ /**
+ * Sends 50 test messages of the specified size, and asserts that all were received.
+ *
+ * @param size The size of the messages to send in bytes.
+ */
+ private void runTestForMessagesOfSize(int size)
+ {
+ Properties testConfig = new Properties();
+ testConfig.put("TEST_NAME", "TC5_PubSubMessageSize");
+ testConfig.put("PUBSUB_KEY", "tc3route");
+ testConfig.put("PUBSUB_NUM_MESSAGES", 10);
+ testConfig.put("PUBSUB_NUM_RECEIVERS", 5);
+ testConfig.put("messageSize", size);
+
+ /*Message[] reports =*/
+ getCircuitFactory().sequenceTest(null, null, testConfig);
+
+ // Compare sender and receivers reports.
+ /*
+ int messagesSent = reports[0].getIntProperty("MESSAGE_COUNT");
+ int messagesReceived = reports[1].getIntProperty("MESSAGE_COUNT");
+
+ Assert.assertEquals("The requested number of messages were not sent.", 50, messagesSent);
+ Assert.assertEquals("Sender and receivers messages sent did not match up.", messagesSent, messagesReceived);
+ */
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as defined in the
+ * interop testing specification. For example the method "testP2P" might map onto the interop test case name
+ * "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "TC5_PubSubMessageSize";
+ }
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
index 5ed502287d..63e2c75509 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedClientTestCase.java
@@ -1,906 +1,906 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sustained;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
-import org.apache.qpid.test.framework.distributedtesting.TestClient;
-import org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub;
-import org.apache.qpid.test.framework.TestUtils;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
- * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
- * messages sent/received.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Supply the name of the test case that this implements.
- * <tr><td> Accept/Reject invites based on test parameters.
- * <tr><td> Adapt to assigned roles.
- * <tr><td> Send required number of test messages using pub/sub. <tr><td> Generate test reports.
- * </table>
- */
-public class SustainedClientTestCase extends TestCase3BasicPubSub implements ExceptionListener, MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(SustainedClientTestCase.class);
-
- /** Used to log to the console. */
- private static final Logger console = Logger.getLogger("SustainedTest");
-
- /** The role to be played by the test. */
- private Roles role;
-
- /** The number of receivers connection to use. */
- private int numReceivers;
-
- /** The routing key to send them to on the default direct exchange. */
- private Destination sendDestination;
-
- /** The routing key to send updates to on the default direct exchange. */
- private Destination sendUpdateDestination;
-
- /** The connections to send/receive the test messages on. */
- private Connection[] connection;
-
- /** The sessions to send/receive the test messages on. */
- private Session[] session;
-
- /** The producer to send the test messages with. */
- MessageProducer producer;
-
- /** Adapter that adjusts the send rate based on the updates from clients. */
- SustainedRateAdapter _rateAdapter;
-
- /** */
- int _batchSize;
-
- private static final long TEN_MILLI_SEC = 10000000;
- private static final int DEBUG_LOG_UPATE_INTERVAL = 10;
- private static final int LOG_UPATE_INTERVAL = 10;
- private static final boolean SLEEP_PER_MESSAGE = Boolean.getBoolean("sleepPerMessage");
-
- /**
- * Should provide the name of the test case that this class implements. The exact names are defined in the interop
- * testing spec.
- *
- * @return The name of the test case that this implements.
- */
- public String getName()
- {
- log.debug("public String getName(): called");
-
- return "Perf_SustainedPubSub";
- }
-
- /**
- * Assigns the role to be played by this test case. The test parameters are fully specified in the assignment
- * message. When this method return the test case will be ready to execute.
- *
- * @param role The role to be played; sender or receivers.
- * @param assignRoleMessage The role assingment message, contains the full test parameters.
- *
- * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
- */
- public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
- {
- log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
- + "): called");
-
- // Take note of the role to be played.
- this.role = role;
-
- // Extract and retain the test parameters.
- numReceivers = assignRoleMessage.getIntProperty("SUSTAINED_NUM_RECEIVERS");
- _batchSize = assignRoleMessage.getIntProperty("SUSTAINED_UPDATE_INTERVAL");
- String sendKey = assignRoleMessage.getStringProperty("SUSTAINED_KEY");
- String sendUpdateKey = assignRoleMessage.getStringProperty("SUSTAINED_UPDATE_KEY");
- int ackMode = assignRoleMessage.getIntProperty("ACKNOWLEDGE_MODE");
- String clientName = assignRoleMessage.getStringProperty("CLIENT_NAME");
-
- if (log.isDebugEnabled())
- {
- log.debug("numReceivers = " + numReceivers);
- log.debug("_batchSize = " + _batchSize);
- log.debug("ackMode = " + ackMode);
- log.debug("sendKey = " + sendKey);
- log.debug("sendUpdateKey = " + sendUpdateKey);
- log.debug("role = " + role);
- }
-
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a single message producer if so.
- case SENDER:
- console.info("Creating Sender");
- // Create a new connection to pass the test messages on.
- connection = new Connection[1];
- session = new Session[1];
-
- connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
- session[0] = connection[0].createSession(false, ackMode);
-
- // Extract and retain the test parameters.
- sendDestination = session[0].createTopic(sendKey);
-
- connection[0].setExceptionListener(this);
-
- producer = session[0].createProducer(sendDestination);
-
- sendUpdateDestination = session[0].createTopic(sendUpdateKey);
- MessageConsumer updateConsumer = session[0].createConsumer(sendUpdateDestination);
-
- _rateAdapter = new SustainedRateAdapter(this);
- updateConsumer.setMessageListener(_rateAdapter);
-
- break;
-
- // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
- // of receivers connections.
- case RECEIVER:
- console.info("Creating Receiver");
- // Create the required number of receivers connections.
- connection = new Connection[numReceivers];
- session = new Session[numReceivers];
-
- for (int i = 0; i < numReceivers; i++)
- {
- connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
- session[i] = connection[i].createSession(false, ackMode);
-
- sendDestination = session[i].createTopic(sendKey);
-
- sendUpdateDestination = session[i].createTopic(sendUpdateKey);
-
- MessageConsumer consumer = session[i].createConsumer(sendDestination);
-
- consumer.setMessageListener(new SustainedListener(clientName + "-" + i, _batchSize, session[i],
- sendUpdateDestination));
- }
-
- break;
- }
-
- // Start all the connection dispatcher threads running.
- for (int i = 0; i < connection.length; i++)
- {
- connection[i].start();
- }
- }
-
- /** Performs the test case actions.
- * @param numMessages*/
- public void start(int numMessages) throws JMSException
- {
- log.debug("public void start(): called");
-
- // Check that the sender role is being performed.
- switch (role)
- {
- // Check if the sender role is being assigned, and set up a single message producer if so.
- case SENDER:
- _rateAdapter.run();
- break;
- case RECEIVER:
-
- }
-
- // return from here when you have finished the test.. this will signal the controller and
- }
-
- public void terminate() throws JMSException, InterruptedException
- {
- if (_rateAdapter != null)
- {
- _rateAdapter.stop();
- }
- }
-
- /**
- * Gets a report on the actions performed by the test case in its assigned role.
- *
- * @param session The controlSession to create the report message in.
- *
- * @return The report message.
- *
- * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
- */
- public Message getReport(Session session) throws JMSException
- {
- log.debug("public Message getReport(Session controlSession): called");
-
- // Close the test connections.
- for (int i = 0; i < connection.length; i++)
- {
- connection[i].close();
- }
-
- Message report = session.createMessage();
- report.setStringProperty("CONTROL_TYPE", "REPORT");
-
- return report;
- }
-
- public void onException(JMSException jmsException)
- {
- Exception linked = jmsException.getLinkedException();
-
- if (linked != null)
- {
- if (log.isDebugEnabled())
- {
- log.debug("Linked Exception:" + linked);
- }
-
- if ((linked instanceof AMQNoRouteException) || (linked instanceof AMQNoConsumersException))
- {
- if (log.isDebugEnabled())
- {
- if (linked instanceof AMQNoConsumersException)
- {
- log.warn("No clients currently available for message:"
- + ((AMQNoConsumersException) linked).getUndeliveredMessage());
- }
- else
- {
- log.warn("No route for message");
- }
- }
-
- // Tell the rate adapter that there are no clients ready yet
- _rateAdapter.NO_CLIENTS = true;
- }
- }
- else
- {
- log.warn("Exception:" + linked);
- }
- }
-
- /**
- * Inner class that listens for messages and sends a report for the time taken between receiving the 'start' and
- * 'end' messages.
- */
- class SustainedListener implements MessageListener
- {
- /** Number of messages received */
- private long _received = 0;
- /** The number of messages in the batch */
- private int _batchSize = 0;
- /** Record of the when the 'start' messagse was sen */
- private Long _startTime;
- /** Message producer to use to send reports */
- MessageProducer _updater;
- /** Session to create the report message on */
- Session _session;
- /** Record of the client ID used for this SustainedListnener */
- String _client;
-
- /**
- * Main Constructor
- *
- * @param clientname The _client id used to identify this connection.
- * @param batchSize The number of messages that are to be sent per batch. Note: This is not used to
- * control the interval between sending reports.
- * @param session The controlSession used for communication.
- * @param sendDestination The destination that update reports should be sent to.
- *
- * @throws JMSException My occur if creatingthe Producer fails
- */
- public SustainedListener(String clientname, int batchSize, Session session, Destination sendDestination)
- throws JMSException
- {
- _batchSize = batchSize;
- _client = clientname;
- _session = session;
- _updater = session.createProducer(sendDestination);
- }
-
- public void onMessage(Message message)
- {
- if (log.isDebugEnabled())
- {
- log.debug("Message " + _received + "received in listener");
- }
-
- if (message instanceof TextMessage)
- {
- try
- {
- _received++;
- if (((TextMessage) message).getText().equals("start"))
- {
- log.debug("Starting Batch");
- _startTime = System.nanoTime();
- }
- else if (((TextMessage) message).getText().equals("end"))
- {
- if (_startTime != null)
- {
- long currentTime = System.nanoTime();
- sendStatus(currentTime - _startTime, _received, message.getIntProperty("BATCH"));
- log.debug("End Batch");
- }
- }
- }
- catch (JMSException e)
- {
- // ignore error
- }
- }
-
- }
-
- /**
- * sendStatus creates and sends the report back to the publisher
- *
- * @param time taken for the the last batch
- * @param received Total number of messages received.
- * @param batchNumber the batch number
- * @throws JMSException if an error occurs during the send
- */
- private void sendStatus(long time, long received, int batchNumber) throws JMSException
- {
- Message updateMessage = _session.createTextMessage("update");
- updateMessage.setStringProperty("CLIENT_ID", ":" + _client);
- updateMessage.setStringProperty("CONTROL_TYPE", "UPDATE");
- updateMessage.setLongProperty("RECEIVED", received);
- updateMessage.setIntProperty("BATCH", batchNumber);
- updateMessage.setLongProperty("DURATION", time);
-
- if (log.isInfoEnabled())
- {
- log.info("**** SENDING [" + batchNumber + "]**** " + "CLIENT_ID:" + _client + " RECEIVED:" + received
- + " BATCH:" + batchNumber + " DURATION:" + time);
- }
-
- // Output on the main console.info the details of this batch
- if ((batchNumber % 10) == 0)
- {
- console.info("Sending Report [" + batchNumber + "] " + "CLIENT_ID:" + _client + " RECEIVED:" + received
- + " BATCH:" + batchNumber + " DURATION:" + time);
- }
-
- _updater.send(updateMessage);
- }
- }
-
- /**
- * This class is used here to adjust the _delay value which in turn is used to control the number of messages/second
- * that are sent through the test system.
- *
- * By keeping a record of the messages recevied and the average time taken to process the batch size can be
- * calculated and so the delay can be adjusted to maintain that rate.
- *
- * Given that delays of < 10ms can be rounded up the delay is only used between messages if the _delay > 10ms * no
- * messages in the batch. Otherwise the delay is used at the end of the batch.
- */
- class SustainedRateAdapter implements MessageListener, Runnable
- {
- private SustainedClientTestCase _client;
- private long _batchVariance = Integer.getInteger("batchVariance", 3); // no. batches to allow drifting
- private long _timeVariance = TEN_MILLI_SEC * 5; // no. nanos between send and report delay (10ms)
- private volatile long _delay; // in nanos
- private long _sent;
- private Map<String, Long> _slowClients = new HashMap<String, Long>();
- private static final long PAUSE_SLEEP = TEN_MILLI_SEC / 1000; // 10 ms
- private static final long NO_CLIENT_SLEEP = 1000; // 1s
- private volatile boolean NO_CLIENTS = true;
- private int _delayShifting;
- private final int REPORTS_WITHOUT_CHANGE = Integer.getInteger("stableReportCount", 5);
- private boolean _warmedup = false;
- private static final long EXPECTED_TIME_PER_BATCH = 100000L;
- private int _warmUpBatches = Integer.getInteger("warmUpBatches", 10);
-
- SustainedRateAdapter(SustainedClientTestCase client)
- {
- _client = client;
- }
-
- public void onMessage(Message message)
- {
- if (log.isDebugEnabled())
- {
- log.debug("SustainedRateAdapter onMessage(Message message = " + message + "): called");
- }
-
- try
- {
- String controlType = message.getStringProperty("CONTROL_TYPE");
-
- // Check if the message is a test invite.
- if ("UPDATE".equals(controlType))
- {
- NO_CLIENTS = false;
- long duration = message.getLongProperty("DURATION");
- long totalReceived = message.getLongProperty("RECEIVED");
- String client = message.getStringProperty("CLIENT_ID");
- int batchNumber = message.getIntProperty("BATCH");
-
- if (log.isInfoEnabled() && ((batchNumber % DEBUG_LOG_UPATE_INTERVAL) == 0))
- {
- log.info("Update Report: CLIENT_ID:" + client + " RECEIVED:" + totalReceived + " Recevied BATCH:"
- + batchNumber + " DURATION:" + duration);
- }
-
- recordSlow(client, totalReceived, batchNumber);
-
- adjustDelay(client, batchNumber, duration);
-
- // Warm up completes when:
- // we haven't warmed up
- // and the number of batches sent to each client is at least half of the required warmup batches
- if (!_warmedup && (batchNumber >= _warmUpBatches))
- {
- _warmedup = true;
- _warmup.countDown();
-
- }
- }
- }
- catch (JMSException e)
- {
- //
- }
- }
-
- CountDownLatch _warmup = new CountDownLatch(1);
-
- int _numBatches = 10000;
-
- // long[] _timings = new long[_numBatches];
- private boolean _running = true;
-
- public void run()
- {
- console.info("Warming up");
-
- doBatch(_warmUpBatches);
-
- try
- {
- // wait for warmup to complete.
- _warmup.await();
-
- // set delay to the average length of the batches
- _delay = _totalDuration / _warmUpBatches / delays.size();
-
- console.info("Warmup complete delay set : " + _delay + " based on _totalDuration: " + _totalDuration
- + " over no. batches: " + _warmUpBatches + " with client count: " + delays.size());
-
- _totalDuration = 0L;
- _totalReceived = 0L;
- _sent = 0L;
- }
- catch (InterruptedException e)
- {
- //
- }
-
- doBatch(_numBatches);
-
- }
-
- private void doBatch(int batchSize) // long[] timings,
- {
- TextMessage testMessage = null;
- try
- {
- testMessage = _client.session[0].createTextMessage("start");
-
- for (int batch = 0; batch <= batchSize; batch++)
- // while (_running)
- {
- long start = System.nanoTime();
-
- testMessage.setText("start");
- testMessage.setIntProperty("BATCH", batch);
-
- _client.producer.send(testMessage);
- _rateAdapter.sentMessage();
-
- testMessage.setText("test");
- // start at 2 so start and end count as part of batch
- for (int m = 2; m < _batchSize; m++)
- {
- _client.producer.send(testMessage);
- _rateAdapter.sentMessage();
- }
-
- testMessage.setText("end");
- _client.producer.send(testMessage);
- _rateAdapter.sentMessage();
-
- long end = System.nanoTime();
-
- long sendtime = end - start;
-
- if (log.isDebugEnabled())
- {
- log.info("Sent batch[" + batch + "](" + _batchSize + ") in " + sendtime); // timings[batch]);
- }
-
- if ((batch % LOG_UPATE_INTERVAL) == 0)
- {
- console.info("Sent Batch[" + batch + "](" + _batchSize + ")" + status());
- }
-
- _rateAdapter.sleepBatch();
-
- }
- }
- catch (JMSException e)
- {
- console.error("Runner ended");
- }
- }
-
- private String status()
- {
- return " TotalDuration: " + _totalDuration + " for " + delays.size() + " consumers" + " Delay is " + _delay
- + " resulting in "
- + ((_delay > (TEN_MILLI_SEC * _batchSize)) ? ((_delay / _batchSize) + "/msg") : (_delay + "/batch"));
- }
-
- private void sleepBatch()
- {
- if (checkForSlowClients())
- { // if there werwe slow clients we have already slept so don't sleep anymore again.
- return;
- }
-
- if (!SLEEP_PER_MESSAGE)
- {
- // per batch sleep.. if sleep is to small to spread over the batch.
- if (_delay <= (TEN_MILLI_SEC * _batchSize))
- {
- sleepLong(_delay);
- }
- else
- {
- log.info("Not sleeping _delay > ten*batch is:" + _delay);
- }
- }
- }
-
- public void stop()
- {
- _running = false;
- }
-
- Map<String, Long> delays = new HashMap<String, Long>();
- Long _totalReceived = 0L;
- Long _totalDuration = 0L;
- int _skipUpdate = 0;
-
- /**
- * Adjust the delay for sending messages based on this update from the client
- *
- * @param client The client that send this update
- * @param duration The time taken for the last batch of messagse
- * @param batchNumber The reported batchnumber from the client
- */
- private void adjustDelay(String client, int batchNumber, long duration)
- {
- // Retrieve the current total time taken for this client.
- Long currentTime = delays.get(client);
-
- // Add the new duration time to this client
- if (currentTime == null)
- {
- currentTime = duration;
- }
- else
- {
- currentTime += duration;
- }
-
- delays.put(client, currentTime);
-
- long batchesSent = _sent / _batchSize;
-
- // ensure we don't divide by zero
- if (batchesSent == 0)
- {
- batchesSent = 1L;
- }
-
- _totalReceived += _batchSize;
- _totalDuration += duration;
-
- // calculate average duration accross clients per batch
- long averageDuration = _totalDuration / delays.size() / batchesSent;
-
- // calculate the difference between current send delay and average report delay
- long diff = (duration) - averageDuration;
-
- if (log.isInfoEnabled() && ((batchNumber % DEBUG_LOG_UPATE_INTERVAL) == 0))
- {
- log.info("TotalDuration:" + _totalDuration + " for " + delays.size() + " consumers." + " on batch: "
- + batchesSent + " received batch: " + batchNumber + " Batch Duration: " + duration + " Average: "
- + averageDuration + " so diff: " + diff + " for : " + client + " Delay is " + _delay + " resulting in "
- + ((_delay > (TEN_MILLI_SEC * _batchSize)) ? ((_delay / _batchSize) + "/msg") : (_delay + "/batch")));
- }
-
- // if the averageDuration differs from the current by more than the specified variane then adjust delay.
- if (Math.abs(diff) > _timeVariance)
- {
-
- // if the the _delay is larger than the required duration to send report
- // speed up
- if (diff > TEN_MILLI_SEC)
- {
- _delay -= TEN_MILLI_SEC;
-
- if (_delay < 0)
- {
- _delay = 0;
- log.info("Reset _delay to 0");
- delayStable();
- }
- else
- {
- delayChanged();
- }
-
- }
- else if (diff < 0) // diff < 0 diff cannot be 0 as it is > _timeVariance
- {
- // the report took longer
- _delay += TEN_MILLI_SEC;
- delayChanged();
- }
- }
- else
- {
- delayStable();
- }
-
- // If we have a consumer that is behind with the batches.
- if ((batchesSent - batchNumber) > _batchVariance)
- {
- log.debug("Increasing _delay as sending more than receiving");
-
- _delay += 2 * TEN_MILLI_SEC;
- delayChanged();
- }
-
- }
-
- /** Reset the number of iterations before we say the delay has stabilised. */
- private void delayChanged()
- {
- _delayShifting = REPORTS_WITHOUT_CHANGE;
- }
-
- /**
- * Record the fact that delay has stabilised If delay has stablised for REPORTS_WITHOUT_CHANGE then it will
- * output Delay stabilised
- */
- private void delayStable()
- {
- _delayShifting--;
-
- if (_delayShifting < 0)
- {
- _delayShifting = 0;
- console.debug("Delay stabilised:" + _delay);
- }
- }
-
- /**
- * Checks that the client has received enough messages. If the client has fallen behind then they are put in the
- * _slowClients lists which will increase the delay.
- *
- * @param client The client identifier to check
- * @param received the number of messages received by that client
- * @param batchNumber
- */
- private void recordSlow(String client, long received, int batchNumber)
- {
- if (Math.abs(batchNumber - (_sent / _batchSize)) > _batchVariance)
- {
- _slowClients.put(client, received);
- }
- else
- {
- _slowClients.remove(client);
- }
- }
-
- /** Incrment the number of sent messages and then sleep, if required. */
- public void sentMessage()
- {
-
- _sent++;
-
- if (_delay > (TEN_MILLI_SEC * _batchSize))
- {
- long batchDelay = _delay / _batchSize;
- // less than 10ms sleep doesn't always work.
- // _delay is in nano seconds
- // if (batchDelay < (TEN_MILLI_SEC))
- // {
- // sleep(0, (int) batchDelay);
- // }
- // else
- {
- // if (batchDelay < 30000000000L)
- {
- sleepLong(batchDelay);
- }
- }
- }
- else
- {
- if (SLEEP_PER_MESSAGE && (_delay > 0))
- {
- sleepLong(_delay / _batchSize);
- }
- }
- }
-
- /**
- * Check at the end of each batch and pause sending messages to allow slow clients to catch up.
- *
- * @return true if there were slow clients that caught up.
- */
- private boolean checkForSlowClients()
- {
- // This will allways be true as we are running this at the end of each batchSize
- // if (_sent % _batchSize == 0)
- {
- // Cause test to pause when we have slow
- if (!_slowClients.isEmpty() || NO_CLIENTS)
- {
-
- while (!_slowClients.isEmpty())
- {
- if (log.isInfoEnabled() && ((_sent / _batchSize % DEBUG_LOG_UPATE_INTERVAL) == 0))
- {
- String clients = "";
- Iterator it = _slowClients.keySet().iterator();
- while (it.hasNext())
- {
- clients += it.next();
- if (it.hasNext())
- {
- clients += ", ";
- }
- }
-
- log.info("Pausing for slow clients:" + clients);
- }
-
- if (console.isDebugEnabled() && ((_sent / _batchSize % LOG_UPATE_INTERVAL) == 0))
- {
- console.debug(_slowClients.size() + " slow clients.");
- }
-
- sleep(PAUSE_SLEEP);
- }
-
- if (NO_CLIENTS)
- {
- sleep(NO_CLIENT_SLEEP);
- }
-
- log.debug("Continuing");
-
- return true;
- }
- else
- {
- if ((_sent / _batchSize % LOG_UPATE_INTERVAL) == 0)
- {
- console.info("Total Delay :" + _delay + " "
- + ((_delayShifting == 0) ? "Stablised" : ("Not Stablised(" + _delayShifting + ")")));
- }
- }
-
- }
-
- return false;
- }
-
- /**
- * Sleep normally takes micro-seconds this allows the use of a nano-second value.
- *
- * @param delay nanoseconds to sleep for.
- */
- private void sleepLong(long delay)
- {
- sleep(delay / 1000000, (int) (delay % 1000000));
- }
-
- /**
- * Sleep for the specified micro-seconds.
- * @param sleep microseconds to sleep for.
- */
- private void sleep(long sleep)
- {
- sleep(sleep, 0);
- }
-
- /**
- * Perform the sleep , swallowing any InteruptException.
- *
- * NOTE: If a sleep request is > 10s then reset only sleep for 5s
- *
- * @param milli to sleep for
- * @param nano sub miliseconds to sleep for
- */
- private void sleep(long milli, int nano)
- {
- try
- {
- log.debug("Sleep:" + milli + ":" + nano);
- if (milli > 10000)
- {
-
- if (_delay == milli)
- {
- _totalDuration = _totalReceived / _batchSize * EXPECTED_TIME_PER_BATCH;
- log.error("Sleeping for more than 10 seconds adjusted to 5s!:" + (milli / 1000)
- + "s. Reset _totalDuration:" + _totalDuration);
- }
- else
- {
- log.error("Sleeping for more than 10 seconds adjusted to 5s!:" + (milli / 1000) + "s");
- }
-
- milli = 5000;
- }
-
- Thread.sleep(milli, nano);
- }
- catch (InterruptedException e)
- {
- //
- }
- }
-
- public void setClient(SustainedClientTestCase client)
- {
- _client = client;
- }
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sustained;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+import org.apache.qpid.test.framework.distributedtesting.TestClient;
+import org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub;
+import org.apache.qpid.test.framework.TestUtils;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Implements test case 3, basic pub/sub. Sends/received a specified number of messages to a specified route on the
+ * default topic exchange, using the specified number of receivers connections. Produces reports on the actual number of
+ * messages sent/received.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Supply the name of the test case that this implements.
+ * <tr><td> Accept/Reject invites based on test parameters.
+ * <tr><td> Adapt to assigned roles.
+ * <tr><td> Send required number of test messages using pub/sub. <tr><td> Generate test reports.
+ * </table>
+ */
+public class SustainedClientTestCase extends TestCase3BasicPubSub implements ExceptionListener, MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(SustainedClientTestCase.class);
+
+ /** Used to log to the console. */
+ private static final Logger console = Logger.getLogger("SustainedTest");
+
+ /** The role to be played by the test. */
+ private Roles role;
+
+ /** The number of receivers connection to use. */
+ private int numReceivers;
+
+ /** The routing key to send them to on the default direct exchange. */
+ private Destination sendDestination;
+
+ /** The routing key to send updates to on the default direct exchange. */
+ private Destination sendUpdateDestination;
+
+ /** The connections to send/receive the test messages on. */
+ private Connection[] connection;
+
+ /** The sessions to send/receive the test messages on. */
+ private Session[] session;
+
+ /** The producer to send the test messages with. */
+ MessageProducer producer;
+
+ /** Adapter that adjusts the send rate based on the updates from clients. */
+ SustainedRateAdapter _rateAdapter;
+
+ /** */
+ int _batchSize;
+
+ private static final long TEN_MILLI_SEC = 10000000;
+ private static final int DEBUG_LOG_UPATE_INTERVAL = 10;
+ private static final int LOG_UPATE_INTERVAL = 10;
+ private static final boolean SLEEP_PER_MESSAGE = Boolean.getBoolean("sleepPerMessage");
+
+ /**
+ * Should provide the name of the test case that this class implements. The exact names are defined in the interop
+ * testing spec.
+ *
+ * @return The name of the test case that this implements.
+ */
+ public String getName()
+ {
+ log.debug("public String getName(): called");
+
+ return "Perf_SustainedPubSub";
+ }
+
+ /**
+ * Assigns the role to be played by this test case. The test parameters are fully specified in the assignment
+ * message. When this method return the test case will be ready to execute.
+ *
+ * @param role The role to be played; sender or receivers.
+ * @param assignRoleMessage The role assingment message, contains the full test parameters.
+ *
+ * @throws JMSException Any JMSException resulting from reading the message are allowed to fall through.
+ */
+ public void assignRole(Roles role, Message assignRoleMessage) throws JMSException
+ {
+ log.debug("public void assignRole(Roles role = " + role + ", Message assignRoleMessage = " + assignRoleMessage
+ + "): called");
+
+ // Take note of the role to be played.
+ this.role = role;
+
+ // Extract and retain the test parameters.
+ numReceivers = assignRoleMessage.getIntProperty("SUSTAINED_NUM_RECEIVERS");
+ _batchSize = assignRoleMessage.getIntProperty("SUSTAINED_UPDATE_INTERVAL");
+ String sendKey = assignRoleMessage.getStringProperty("SUSTAINED_KEY");
+ String sendUpdateKey = assignRoleMessage.getStringProperty("SUSTAINED_UPDATE_KEY");
+ int ackMode = assignRoleMessage.getIntProperty("ACKNOWLEDGE_MODE");
+ String clientName = assignRoleMessage.getStringProperty("CLIENT_NAME");
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("numReceivers = " + numReceivers);
+ log.debug("_batchSize = " + _batchSize);
+ log.debug("ackMode = " + ackMode);
+ log.debug("sendKey = " + sendKey);
+ log.debug("sendUpdateKey = " + sendUpdateKey);
+ log.debug("role = " + role);
+ }
+
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case SENDER:
+ console.info("Creating Sender");
+ // Create a new connection to pass the test messages on.
+ connection = new Connection[1];
+ session = new Session[1];
+
+ connection[0] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[0] = connection[0].createSession(false, ackMode);
+
+ // Extract and retain the test parameters.
+ sendDestination = session[0].createTopic(sendKey);
+
+ connection[0].setExceptionListener(this);
+
+ producer = session[0].createProducer(sendDestination);
+
+ sendUpdateDestination = session[0].createTopic(sendUpdateKey);
+ MessageConsumer updateConsumer = session[0].createConsumer(sendUpdateDestination);
+
+ _rateAdapter = new SustainedRateAdapter(this);
+ updateConsumer.setMessageListener(_rateAdapter);
+
+ break;
+
+ // Otherwise the receivers role is being assigned, so set this up to listen for messages on the required number
+ // of receivers connections.
+ case RECEIVER:
+ console.info("Creating Receiver");
+ // Create the required number of receivers connections.
+ connection = new Connection[numReceivers];
+ session = new Session[numReceivers];
+
+ for (int i = 0; i < numReceivers; i++)
+ {
+ connection[i] = TestUtils.createConnection(TestClient.testContextProperties);
+ session[i] = connection[i].createSession(false, ackMode);
+
+ sendDestination = session[i].createTopic(sendKey);
+
+ sendUpdateDestination = session[i].createTopic(sendUpdateKey);
+
+ MessageConsumer consumer = session[i].createConsumer(sendDestination);
+
+ consumer.setMessageListener(new SustainedListener(clientName + "-" + i, _batchSize, session[i],
+ sendUpdateDestination));
+ }
+
+ break;
+ }
+
+ // Start all the connection dispatcher threads running.
+ for (int i = 0; i < connection.length; i++)
+ {
+ connection[i].start();
+ }
+ }
+
+ /** Performs the test case actions.
+ * @param numMessages*/
+ public void start(int numMessages) throws JMSException
+ {
+ log.debug("public void start(): called");
+
+ // Check that the sender role is being performed.
+ switch (role)
+ {
+ // Check if the sender role is being assigned, and set up a single message producer if so.
+ case SENDER:
+ _rateAdapter.run();
+ break;
+ case RECEIVER:
+
+ }
+
+ // return from here when you have finished the test.. this will signal the controller and
+ }
+
+ public void terminate() throws JMSException, InterruptedException
+ {
+ if (_rateAdapter != null)
+ {
+ _rateAdapter.stop();
+ }
+ }
+
+ /**
+ * Gets a report on the actions performed by the test case in its assigned role.
+ *
+ * @param session The controlSession to create the report message in.
+ *
+ * @return The report message.
+ *
+ * @throws JMSException Any JMSExceptions resulting from creating the report are allowed to fall through.
+ */
+ public Message getReport(Session session) throws JMSException
+ {
+ log.debug("public Message getReport(Session controlSession): called");
+
+ // Close the test connections.
+ for (int i = 0; i < connection.length; i++)
+ {
+ connection[i].close();
+ }
+
+ Message report = session.createMessage();
+ report.setStringProperty("CONTROL_TYPE", "REPORT");
+
+ return report;
+ }
+
+ public void onException(JMSException jmsException)
+ {
+ Exception linked = jmsException.getLinkedException();
+
+ if (linked != null)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Linked Exception:" + linked);
+ }
+
+ if ((linked instanceof AMQNoRouteException) || (linked instanceof AMQNoConsumersException))
+ {
+ if (log.isDebugEnabled())
+ {
+ if (linked instanceof AMQNoConsumersException)
+ {
+ log.warn("No clients currently available for message:"
+ + ((AMQNoConsumersException) linked).getUndeliveredMessage());
+ }
+ else
+ {
+ log.warn("No route for message");
+ }
+ }
+
+ // Tell the rate adapter that there are no clients ready yet
+ _rateAdapter.NO_CLIENTS = true;
+ }
+ }
+ else
+ {
+ log.warn("Exception:" + linked);
+ }
+ }
+
+ /**
+ * Inner class that listens for messages and sends a report for the time taken between receiving the 'start' and
+ * 'end' messages.
+ */
+ class SustainedListener implements MessageListener
+ {
+ /** Number of messages received */
+ private long _received = 0;
+ /** The number of messages in the batch */
+ private int _batchSize = 0;
+ /** Record of the when the 'start' messagse was sen */
+ private Long _startTime;
+ /** Message producer to use to send reports */
+ MessageProducer _updater;
+ /** Session to create the report message on */
+ Session _session;
+ /** Record of the client ID used for this SustainedListnener */
+ String _client;
+
+ /**
+ * Main Constructor
+ *
+ * @param clientname The _client id used to identify this connection.
+ * @param batchSize The number of messages that are to be sent per batch. Note: This is not used to
+ * control the interval between sending reports.
+ * @param session The controlSession used for communication.
+ * @param sendDestination The destination that update reports should be sent to.
+ *
+ * @throws JMSException My occur if creatingthe Producer fails
+ */
+ public SustainedListener(String clientname, int batchSize, Session session, Destination sendDestination)
+ throws JMSException
+ {
+ _batchSize = batchSize;
+ _client = clientname;
+ _session = session;
+ _updater = session.createProducer(sendDestination);
+ }
+
+ public void onMessage(Message message)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Message " + _received + "received in listener");
+ }
+
+ if (message instanceof TextMessage)
+ {
+ try
+ {
+ _received++;
+ if (((TextMessage) message).getText().equals("start"))
+ {
+ log.debug("Starting Batch");
+ _startTime = System.nanoTime();
+ }
+ else if (((TextMessage) message).getText().equals("end"))
+ {
+ if (_startTime != null)
+ {
+ long currentTime = System.nanoTime();
+ sendStatus(currentTime - _startTime, _received, message.getIntProperty("BATCH"));
+ log.debug("End Batch");
+ }
+ }
+ }
+ catch (JMSException e)
+ {
+ // ignore error
+ }
+ }
+
+ }
+
+ /**
+ * sendStatus creates and sends the report back to the publisher
+ *
+ * @param time taken for the the last batch
+ * @param received Total number of messages received.
+ * @param batchNumber the batch number
+ * @throws JMSException if an error occurs during the send
+ */
+ private void sendStatus(long time, long received, int batchNumber) throws JMSException
+ {
+ Message updateMessage = _session.createTextMessage("update");
+ updateMessage.setStringProperty("CLIENT_ID", ":" + _client);
+ updateMessage.setStringProperty("CONTROL_TYPE", "UPDATE");
+ updateMessage.setLongProperty("RECEIVED", received);
+ updateMessage.setIntProperty("BATCH", batchNumber);
+ updateMessage.setLongProperty("DURATION", time);
+
+ if (log.isInfoEnabled())
+ {
+ log.info("**** SENDING [" + batchNumber + "]**** " + "CLIENT_ID:" + _client + " RECEIVED:" + received
+ + " BATCH:" + batchNumber + " DURATION:" + time);
+ }
+
+ // Output on the main console.info the details of this batch
+ if ((batchNumber % 10) == 0)
+ {
+ console.info("Sending Report [" + batchNumber + "] " + "CLIENT_ID:" + _client + " RECEIVED:" + received
+ + " BATCH:" + batchNumber + " DURATION:" + time);
+ }
+
+ _updater.send(updateMessage);
+ }
+ }
+
+ /**
+ * This class is used here to adjust the _delay value which in turn is used to control the number of messages/second
+ * that are sent through the test system.
+ *
+ * By keeping a record of the messages recevied and the average time taken to process the batch size can be
+ * calculated and so the delay can be adjusted to maintain that rate.
+ *
+ * Given that delays of < 10ms can be rounded up the delay is only used between messages if the _delay > 10ms * no
+ * messages in the batch. Otherwise the delay is used at the end of the batch.
+ */
+ class SustainedRateAdapter implements MessageListener, Runnable
+ {
+ private SustainedClientTestCase _client;
+ private long _batchVariance = Integer.getInteger("batchVariance", 3); // no. batches to allow drifting
+ private long _timeVariance = TEN_MILLI_SEC * 5; // no. nanos between send and report delay (10ms)
+ private volatile long _delay; // in nanos
+ private long _sent;
+ private Map<String, Long> _slowClients = new HashMap<String, Long>();
+ private static final long PAUSE_SLEEP = TEN_MILLI_SEC / 1000; // 10 ms
+ private static final long NO_CLIENT_SLEEP = 1000; // 1s
+ private volatile boolean NO_CLIENTS = true;
+ private int _delayShifting;
+ private final int REPORTS_WITHOUT_CHANGE = Integer.getInteger("stableReportCount", 5);
+ private boolean _warmedup = false;
+ private static final long EXPECTED_TIME_PER_BATCH = 100000L;
+ private int _warmUpBatches = Integer.getInteger("warmUpBatches", 10);
+
+ SustainedRateAdapter(SustainedClientTestCase client)
+ {
+ _client = client;
+ }
+
+ public void onMessage(Message message)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("SustainedRateAdapter onMessage(Message message = " + message + "): called");
+ }
+
+ try
+ {
+ String controlType = message.getStringProperty("CONTROL_TYPE");
+
+ // Check if the message is a test invite.
+ if ("UPDATE".equals(controlType))
+ {
+ NO_CLIENTS = false;
+ long duration = message.getLongProperty("DURATION");
+ long totalReceived = message.getLongProperty("RECEIVED");
+ String client = message.getStringProperty("CLIENT_ID");
+ int batchNumber = message.getIntProperty("BATCH");
+
+ if (log.isInfoEnabled() && ((batchNumber % DEBUG_LOG_UPATE_INTERVAL) == 0))
+ {
+ log.info("Update Report: CLIENT_ID:" + client + " RECEIVED:" + totalReceived + " Recevied BATCH:"
+ + batchNumber + " DURATION:" + duration);
+ }
+
+ recordSlow(client, totalReceived, batchNumber);
+
+ adjustDelay(client, batchNumber, duration);
+
+ // Warm up completes when:
+ // we haven't warmed up
+ // and the number of batches sent to each client is at least half of the required warmup batches
+ if (!_warmedup && (batchNumber >= _warmUpBatches))
+ {
+ _warmedup = true;
+ _warmup.countDown();
+
+ }
+ }
+ }
+ catch (JMSException e)
+ {
+ //
+ }
+ }
+
+ CountDownLatch _warmup = new CountDownLatch(1);
+
+ int _numBatches = 10000;
+
+ // long[] _timings = new long[_numBatches];
+ private boolean _running = true;
+
+ public void run()
+ {
+ console.info("Warming up");
+
+ doBatch(_warmUpBatches);
+
+ try
+ {
+ // wait for warmup to complete.
+ _warmup.await();
+
+ // set delay to the average length of the batches
+ _delay = _totalDuration / _warmUpBatches / delays.size();
+
+ console.info("Warmup complete delay set : " + _delay + " based on _totalDuration: " + _totalDuration
+ + " over no. batches: " + _warmUpBatches + " with client count: " + delays.size());
+
+ _totalDuration = 0L;
+ _totalReceived = 0L;
+ _sent = 0L;
+ }
+ catch (InterruptedException e)
+ {
+ //
+ }
+
+ doBatch(_numBatches);
+
+ }
+
+ private void doBatch(int batchSize) // long[] timings,
+ {
+ TextMessage testMessage = null;
+ try
+ {
+ testMessage = _client.session[0].createTextMessage("start");
+
+ for (int batch = 0; batch <= batchSize; batch++)
+ // while (_running)
+ {
+ long start = System.nanoTime();
+
+ testMessage.setText("start");
+ testMessage.setIntProperty("BATCH", batch);
+
+ _client.producer.send(testMessage);
+ _rateAdapter.sentMessage();
+
+ testMessage.setText("test");
+ // start at 2 so start and end count as part of batch
+ for (int m = 2; m < _batchSize; m++)
+ {
+ _client.producer.send(testMessage);
+ _rateAdapter.sentMessage();
+ }
+
+ testMessage.setText("end");
+ _client.producer.send(testMessage);
+ _rateAdapter.sentMessage();
+
+ long end = System.nanoTime();
+
+ long sendtime = end - start;
+
+ if (log.isDebugEnabled())
+ {
+ log.info("Sent batch[" + batch + "](" + _batchSize + ") in " + sendtime); // timings[batch]);
+ }
+
+ if ((batch % LOG_UPATE_INTERVAL) == 0)
+ {
+ console.info("Sent Batch[" + batch + "](" + _batchSize + ")" + status());
+ }
+
+ _rateAdapter.sleepBatch();
+
+ }
+ }
+ catch (JMSException e)
+ {
+ console.error("Runner ended");
+ }
+ }
+
+ private String status()
+ {
+ return " TotalDuration: " + _totalDuration + " for " + delays.size() + " consumers" + " Delay is " + _delay
+ + " resulting in "
+ + ((_delay > (TEN_MILLI_SEC * _batchSize)) ? ((_delay / _batchSize) + "/msg") : (_delay + "/batch"));
+ }
+
+ private void sleepBatch()
+ {
+ if (checkForSlowClients())
+ { // if there werwe slow clients we have already slept so don't sleep anymore again.
+ return;
+ }
+
+ if (!SLEEP_PER_MESSAGE)
+ {
+ // per batch sleep.. if sleep is to small to spread over the batch.
+ if (_delay <= (TEN_MILLI_SEC * _batchSize))
+ {
+ sleepLong(_delay);
+ }
+ else
+ {
+ log.info("Not sleeping _delay > ten*batch is:" + _delay);
+ }
+ }
+ }
+
+ public void stop()
+ {
+ _running = false;
+ }
+
+ Map<String, Long> delays = new HashMap<String, Long>();
+ Long _totalReceived = 0L;
+ Long _totalDuration = 0L;
+ int _skipUpdate = 0;
+
+ /**
+ * Adjust the delay for sending messages based on this update from the client
+ *
+ * @param client The client that send this update
+ * @param duration The time taken for the last batch of messagse
+ * @param batchNumber The reported batchnumber from the client
+ */
+ private void adjustDelay(String client, int batchNumber, long duration)
+ {
+ // Retrieve the current total time taken for this client.
+ Long currentTime = delays.get(client);
+
+ // Add the new duration time to this client
+ if (currentTime == null)
+ {
+ currentTime = duration;
+ }
+ else
+ {
+ currentTime += duration;
+ }
+
+ delays.put(client, currentTime);
+
+ long batchesSent = _sent / _batchSize;
+
+ // ensure we don't divide by zero
+ if (batchesSent == 0)
+ {
+ batchesSent = 1L;
+ }
+
+ _totalReceived += _batchSize;
+ _totalDuration += duration;
+
+ // calculate average duration accross clients per batch
+ long averageDuration = _totalDuration / delays.size() / batchesSent;
+
+ // calculate the difference between current send delay and average report delay
+ long diff = (duration) - averageDuration;
+
+ if (log.isInfoEnabled() && ((batchNumber % DEBUG_LOG_UPATE_INTERVAL) == 0))
+ {
+ log.info("TotalDuration:" + _totalDuration + " for " + delays.size() + " consumers." + " on batch: "
+ + batchesSent + " received batch: " + batchNumber + " Batch Duration: " + duration + " Average: "
+ + averageDuration + " so diff: " + diff + " for : " + client + " Delay is " + _delay + " resulting in "
+ + ((_delay > (TEN_MILLI_SEC * _batchSize)) ? ((_delay / _batchSize) + "/msg") : (_delay + "/batch")));
+ }
+
+ // if the averageDuration differs from the current by more than the specified variane then adjust delay.
+ if (Math.abs(diff) > _timeVariance)
+ {
+
+ // if the the _delay is larger than the required duration to send report
+ // speed up
+ if (diff > TEN_MILLI_SEC)
+ {
+ _delay -= TEN_MILLI_SEC;
+
+ if (_delay < 0)
+ {
+ _delay = 0;
+ log.info("Reset _delay to 0");
+ delayStable();
+ }
+ else
+ {
+ delayChanged();
+ }
+
+ }
+ else if (diff < 0) // diff < 0 diff cannot be 0 as it is > _timeVariance
+ {
+ // the report took longer
+ _delay += TEN_MILLI_SEC;
+ delayChanged();
+ }
+ }
+ else
+ {
+ delayStable();
+ }
+
+ // If we have a consumer that is behind with the batches.
+ if ((batchesSent - batchNumber) > _batchVariance)
+ {
+ log.debug("Increasing _delay as sending more than receiving");
+
+ _delay += 2 * TEN_MILLI_SEC;
+ delayChanged();
+ }
+
+ }
+
+ /** Reset the number of iterations before we say the delay has stabilised. */
+ private void delayChanged()
+ {
+ _delayShifting = REPORTS_WITHOUT_CHANGE;
+ }
+
+ /**
+ * Record the fact that delay has stabilised If delay has stablised for REPORTS_WITHOUT_CHANGE then it will
+ * output Delay stabilised
+ */
+ private void delayStable()
+ {
+ _delayShifting--;
+
+ if (_delayShifting < 0)
+ {
+ _delayShifting = 0;
+ console.debug("Delay stabilised:" + _delay);
+ }
+ }
+
+ /**
+ * Checks that the client has received enough messages. If the client has fallen behind then they are put in the
+ * _slowClients lists which will increase the delay.
+ *
+ * @param client The client identifier to check
+ * @param received the number of messages received by that client
+ * @param batchNumber
+ */
+ private void recordSlow(String client, long received, int batchNumber)
+ {
+ if (Math.abs(batchNumber - (_sent / _batchSize)) > _batchVariance)
+ {
+ _slowClients.put(client, received);
+ }
+ else
+ {
+ _slowClients.remove(client);
+ }
+ }
+
+ /** Incrment the number of sent messages and then sleep, if required. */
+ public void sentMessage()
+ {
+
+ _sent++;
+
+ if (_delay > (TEN_MILLI_SEC * _batchSize))
+ {
+ long batchDelay = _delay / _batchSize;
+ // less than 10ms sleep doesn't always work.
+ // _delay is in nano seconds
+ // if (batchDelay < (TEN_MILLI_SEC))
+ // {
+ // sleep(0, (int) batchDelay);
+ // }
+ // else
+ {
+ // if (batchDelay < 30000000000L)
+ {
+ sleepLong(batchDelay);
+ }
+ }
+ }
+ else
+ {
+ if (SLEEP_PER_MESSAGE && (_delay > 0))
+ {
+ sleepLong(_delay / _batchSize);
+ }
+ }
+ }
+
+ /**
+ * Check at the end of each batch and pause sending messages to allow slow clients to catch up.
+ *
+ * @return true if there were slow clients that caught up.
+ */
+ private boolean checkForSlowClients()
+ {
+ // This will allways be true as we are running this at the end of each batchSize
+ // if (_sent % _batchSize == 0)
+ {
+ // Cause test to pause when we have slow
+ if (!_slowClients.isEmpty() || NO_CLIENTS)
+ {
+
+ while (!_slowClients.isEmpty())
+ {
+ if (log.isInfoEnabled() && ((_sent / _batchSize % DEBUG_LOG_UPATE_INTERVAL) == 0))
+ {
+ String clients = "";
+ Iterator it = _slowClients.keySet().iterator();
+ while (it.hasNext())
+ {
+ clients += it.next();
+ if (it.hasNext())
+ {
+ clients += ", ";
+ }
+ }
+
+ log.info("Pausing for slow clients:" + clients);
+ }
+
+ if (console.isDebugEnabled() && ((_sent / _batchSize % LOG_UPATE_INTERVAL) == 0))
+ {
+ console.debug(_slowClients.size() + " slow clients.");
+ }
+
+ sleep(PAUSE_SLEEP);
+ }
+
+ if (NO_CLIENTS)
+ {
+ sleep(NO_CLIENT_SLEEP);
+ }
+
+ log.debug("Continuing");
+
+ return true;
+ }
+ else
+ {
+ if ((_sent / _batchSize % LOG_UPATE_INTERVAL) == 0)
+ {
+ console.info("Total Delay :" + _delay + " "
+ + ((_delayShifting == 0) ? "Stablised" : ("Not Stablised(" + _delayShifting + ")")));
+ }
+ }
+
+ }
+
+ return false;
+ }
+
+ /**
+ * Sleep normally takes micro-seconds this allows the use of a nano-second value.
+ *
+ * @param delay nanoseconds to sleep for.
+ */
+ private void sleepLong(long delay)
+ {
+ sleep(delay / 1000000, (int) (delay % 1000000));
+ }
+
+ /**
+ * Sleep for the specified micro-seconds.
+ * @param sleep microseconds to sleep for.
+ */
+ private void sleep(long sleep)
+ {
+ sleep(sleep, 0);
+ }
+
+ /**
+ * Perform the sleep , swallowing any InteruptException.
+ *
+ * NOTE: If a sleep request is > 10s then reset only sleep for 5s
+ *
+ * @param milli to sleep for
+ * @param nano sub miliseconds to sleep for
+ */
+ private void sleep(long milli, int nano)
+ {
+ try
+ {
+ log.debug("Sleep:" + milli + ":" + nano);
+ if (milli > 10000)
+ {
+
+ if (_delay == milli)
+ {
+ _totalDuration = _totalReceived / _batchSize * EXPECTED_TIME_PER_BATCH;
+ log.error("Sleeping for more than 10 seconds adjusted to 5s!:" + (milli / 1000)
+ + "s. Reset _totalDuration:" + _totalDuration);
+ }
+ else
+ {
+ log.error("Sleeping for more than 10 seconds adjusted to 5s!:" + (milli / 1000) + "s");
+ }
+
+ milli = 5000;
+ }
+
+ Thread.sleep(milli, nano);
+ }
+ catch (InterruptedException e)
+ {
+ //
+ }
+ }
+
+ public void setClient(SustainedClientTestCase client)
+ {
+ _client = client;
+ }
+ }
+
+}
diff --git a/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java b/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
index 5979a459ec..0077b4727a 100644
--- a/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
+++ b/qpid/java/integrationtests/src/main/java/org/apache/qpid/sustained/SustainedTestCase.java
@@ -1,126 +1,126 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.sustained;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.framework.DropInTest;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import javax.jms.JMSException;
-import javax.jms.Message;
-
-import java.util.Properties;
-
-/**
- * SustainedTestCase is a {@link FrameworkBaseCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
- * test client sending, and several receiving, and attempts to find the highest rate at which messages can be broadcast
- * to the receivers. It is also a {@link DropInTest} to which more test clients may be added during a test run.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- */
-public class SustainedTestCase extends FrameworkBaseCase implements DropInTest
-{
- /** Used for debugging. */
- Logger log = Logger.getLogger(SustainedTestCase.class);
-
- /** Holds the root name of the topic on which to send the test messages. */
- private static final String SUSTAINED_KEY = "Perf_SustainedPubSub";
-
- /**
- * Creates a new coordinating test case with the specified name.
- *
- * @param name The test case name.
- */
- public SustainedTestCase(String name)
- {
- super(name);
- }
-
- /**
- * Performs a single test run of the sustained test.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- public void testBasicPubSub() throws Exception
- {
- log.debug("public void testSinglePubSubCycle(): called");
-
- Properties testConfig = new Properties();
- testConfig.put("TEST_NAME", "Perf_SustainedPubSub");
- testConfig.put("SUSTAINED_KEY", SUSTAINED_KEY);
- testConfig.put("SUSTAINED_NUM_RECEIVERS", Integer.getInteger("numReceives", 2));
- testConfig.put("SUSTAINED_UPDATE_INTERVAL", Integer.getInteger("batchSize", 1000));
- testConfig.put("SUSTAINED_UPDATE_KEY", SUSTAINED_KEY + ".UPDATE");
- testConfig.put("ACKNOWLEDGE_MODE", Integer.getInteger("ackMode", AMQSession.AUTO_ACKNOWLEDGE));
-
- log.info("Created Config: " + testConfig.entrySet().toArray());
-
- getCircuitFactory().sequenceTest(null, null, testConfig);
- }
-
- /**
- * Accepts a late joining client into this test case. The client will be enlisted with a control message
- * with the 'CONTROL_TYPE' field set to the value 'LATEJOIN'. It should also provide values for the fields:
- *
- * <p/><table>
- * <tr><td> CLIENT_NAME <td> A unique name for the new client.
- * <tr><td> CLIENT_PRIVATE_CONTROL_KEY <td> The key for the route on which the client receives its control messages.
- * </table>
- *
- * @param message The late joiners join message.
- *
- * @throws JMSException Any JMS Exception are allowed to fall through, indicating that the join failed.
- */
- public void lateJoin(Message message) throws JMSException
- {
- throw new RuntimeException("Not implemented.");
- /*
- // Extract the joining clients details from its join request message.
- TestClientDetails clientDetails = new TestClientDetails();
- clientDetails.clientName = message.getStringProperty("CLIENT_NAME");
- clientDetails.privateControlKey = message.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
-
- // Register the joining client, but do block for confirmation as cannot do a synchronous receivers during this
- // method call, as it may have been called from an 'onMessage' method.
- assignReceiverRole(clientDetails, new Properties(), false);
- */
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as known to the test
- * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
- * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
- * name "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- *
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- return "Perf_SustainedPubSub";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.sustained;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.framework.DropInTest;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.util.Properties;
+
+/**
+ * SustainedTestCase is a {@link FrameworkBaseCase} that runs the "Perf_SustainedPubSub" test case. This consists of one
+ * test client sending, and several receiving, and attempts to find the highest rate at which messages can be broadcast
+ * to the receivers. It is also a {@link DropInTest} to which more test clients may be added during a test run.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class SustainedTestCase extends FrameworkBaseCase implements DropInTest
+{
+ /** Used for debugging. */
+ Logger log = Logger.getLogger(SustainedTestCase.class);
+
+ /** Holds the root name of the topic on which to send the test messages. */
+ private static final String SUSTAINED_KEY = "Perf_SustainedPubSub";
+
+ /**
+ * Creates a new coordinating test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public SustainedTestCase(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs a single test run of the sustained test.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ public void testBasicPubSub() throws Exception
+ {
+ log.debug("public void testSinglePubSubCycle(): called");
+
+ Properties testConfig = new Properties();
+ testConfig.put("TEST_NAME", "Perf_SustainedPubSub");
+ testConfig.put("SUSTAINED_KEY", SUSTAINED_KEY);
+ testConfig.put("SUSTAINED_NUM_RECEIVERS", Integer.getInteger("numReceives", 2));
+ testConfig.put("SUSTAINED_UPDATE_INTERVAL", Integer.getInteger("batchSize", 1000));
+ testConfig.put("SUSTAINED_UPDATE_KEY", SUSTAINED_KEY + ".UPDATE");
+ testConfig.put("ACKNOWLEDGE_MODE", Integer.getInteger("ackMode", AMQSession.AUTO_ACKNOWLEDGE));
+
+ log.info("Created Config: " + testConfig.entrySet().toArray());
+
+ getCircuitFactory().sequenceTest(null, null, testConfig);
+ }
+
+ /**
+ * Accepts a late joining client into this test case. The client will be enlisted with a control message
+ * with the 'CONTROL_TYPE' field set to the value 'LATEJOIN'. It should also provide values for the fields:
+ *
+ * <p/><table>
+ * <tr><td> CLIENT_NAME <td> A unique name for the new client.
+ * <tr><td> CLIENT_PRIVATE_CONTROL_KEY <td> The key for the route on which the client receives its control messages.
+ * </table>
+ *
+ * @param message The late joiners join message.
+ *
+ * @throws JMSException Any JMS Exception are allowed to fall through, indicating that the join failed.
+ */
+ public void lateJoin(Message message) throws JMSException
+ {
+ throw new RuntimeException("Not implemented.");
+ /*
+ // Extract the joining clients details from its join request message.
+ TestClientDetails clientDetails = new TestClientDetails();
+ clientDetails.clientName = message.getStringProperty("CLIENT_NAME");
+ clientDetails.privateControlKey = message.getStringProperty("CLIENT_PRIVATE_CONTROL_KEY");
+
+ // Register the joining client, but do block for confirmation as cannot do a synchronous receivers during this
+ // method call, as it may have been called from an 'onMessage' method.
+ assignReceiverRole(clientDetails, new Properties(), false);
+ */
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as known to the test
+ * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ * name "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ return "Perf_SustainedPubSub";
+ }
+}
diff --git a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java
index dc74590f60..fdae005f00 100644
--- a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java
+++ b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/IsolatedClassLoader.java
@@ -1,113 +1,113 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.maven;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- *
- * @noinspection CustomClassloader
- */
-public class IsolatedClassLoader extends URLClassLoader
-{
-
- private static final URL[] EMPTY_URL_ARRAY = new URL[0];
- private ClassLoader parent = ClassLoader.getSystemClassLoader();
-
- private Set urls = new HashSet();
-
- private boolean childDelegation = true;
-
- public IsolatedClassLoader()
- {
- super(EMPTY_URL_ARRAY, null);
- }
-
- public IsolatedClassLoader(ClassLoader parent, boolean childDelegation)
- {
- super(EMPTY_URL_ARRAY, parent);
-
- this.childDelegation = childDelegation;
- }
-
- public IsolatedClassLoader(ClassLoader parent)
- {
- super(EMPTY_URL_ARRAY, parent);
- }
-
- public void addURL(URL url)
- {
- // avoid duplicates
- if (!urls.contains(url))
- {
- super.addURL(url);
- urls.add(url);
- }
- }
-
- public synchronized Class loadClass(String name) throws ClassNotFoundException
- {
- Class c;
-
- if (childDelegation)
- {
- c = findLoadedClass(name);
-
- ClassNotFoundException ex = null;
-
- if (c == null)
- {
- try
- {
- c = findClass(name);
- }
- catch (ClassNotFoundException e)
- {
- ex = e;
-
- if (parent != null)
- {
- c = parent.loadClass(name);
- }
- }
- }
-
- if (c == null)
- {
- throw ex;
- }
- }
- else
- {
- c = super.loadClass(name);
- }
-
- return c;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.maven;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @author Rupert Smith
+ *
+ * @noinspection CustomClassloader
+ */
+public class IsolatedClassLoader extends URLClassLoader
+{
+
+ private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+ private ClassLoader parent = ClassLoader.getSystemClassLoader();
+
+ private Set urls = new HashSet();
+
+ private boolean childDelegation = true;
+
+ public IsolatedClassLoader()
+ {
+ super(EMPTY_URL_ARRAY, null);
+ }
+
+ public IsolatedClassLoader(ClassLoader parent, boolean childDelegation)
+ {
+ super(EMPTY_URL_ARRAY, parent);
+
+ this.childDelegation = childDelegation;
+ }
+
+ public IsolatedClassLoader(ClassLoader parent)
+ {
+ super(EMPTY_URL_ARRAY, parent);
+ }
+
+ public void addURL(URL url)
+ {
+ // avoid duplicates
+ if (!urls.contains(url))
+ {
+ super.addURL(url);
+ urls.add(url);
+ }
+ }
+
+ public synchronized Class loadClass(String name) throws ClassNotFoundException
+ {
+ Class c;
+
+ if (childDelegation)
+ {
+ c = findLoadedClass(name);
+
+ ClassNotFoundException ex = null;
+
+ if (c == null)
+ {
+ try
+ {
+ c = findClass(name);
+ }
+ catch (ClassNotFoundException e)
+ {
+ ex = e;
+
+ if (parent != null)
+ {
+ c = parent.loadClass(name);
+ }
+ }
+ }
+
+ if (c == null)
+ {
+ throw ex;
+ }
+ }
+ else
+ {
+ c = super.loadClass(name);
+ }
+
+ return c;
+ }
+}
diff --git a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java
index 442529b609..36e594d9dc 100644
--- a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java
+++ b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestRunnerMojo.java
@@ -1,274 +1,274 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.maven;
-
-import org.apache.maven.plugin.AbstractMojo;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-
-/**
- * TKTestRunnerMojo is a JUnit test runner plugin for Maven 2. It is intended to be compatible with the surefire
- * plugin (though not all features of that are yet implemented), with some extended capabilities.
- *
- * <p/>This plugin adds the ability to use different JUnit test runners, and to pass arbitrary options to them.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- *
- * @goal tktest
- * @phase test
- * @requiresDependencyResolution test
- */
-public class TKTestRunnerMojo extends AbstractMojo
-{
- private static final BitSet UNRESERVED = new BitSet(256);
-
- /**
- * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.
- *
- * @parameter expression="${maven.test.skip}"
- */
- private boolean skip;
-
- /**
- * The TKTest runner command lines. There are passed directly to the TKTestRunner main method.
- *
- * @parameter
- */
- private Map<String, String> commands = new LinkedHashMap<String, String>();
-
- /**
- * The base directory of the project being tested. This can be obtained in your unit test by
- * System.getProperty("basedir").
- *
- * @parameter expression="${basedir}"
- * @required
- */
- private File basedir;
-
- /**
- * The directory containing generated classes of the project being tested.
- *
- * @parameter expression="${project.build.outputDirectory}"
- * @required
- */
- private File classesDirectory;
-
- /**
- * The directory containing generated test classes of the project being tested.
- *
- * @parameter expression="${project.build.testOutputDirectory}"
- * @required
- */
- private File testClassesDirectory;
-
- /**
- * The classpath elements of the project being tested.
- *
- * @parameter expression="${project.testClasspathElements}"
- * @required
- * @readonly
- */
- private List classpathElements;
-
- /**
- * List of System properties to pass to the tests.
- *
- * @parameter
- */
- private Properties systemProperties;
-
- /**
- * Map of of plugin artifacts.
- *
- * @parameter expression="${plugin.artifactMap}"
- * @required
- * @readonly
- */
- private Map pluginArtifactMap;
-
- /**
- * Map of of project artifacts.
- *
- * @parameter expression="${project.artifactMap}"
- * @required
- * @readonly
- */
- private Map projectArtifactMap;
-
- /**
- * Option to specify the forking mode. Can be "never" (default), "once" or "always".
- * "none" and "pertest" are also accepted for backwards compatibility.
- *
- * @parameter expression="${forkMode}" default-value="once"
- */
- private String forkMode;
-
- /**
- * Option to specify the jvm (or path to the java executable) to use with
- * the forking options. For the default we will assume that java is in the path.
- *
- * @parameter expression="${jvm}"
- * default-value="java"
- */
- private String jvm;
-
- /**
- * The test runner to use.
- *
- * @parameter
- */
- private String testrunner;
-
- /**
- * The additional properties to append to the test runner invocation command line.
- *
- * @parameter
- */
- private Properties testrunnerproperties;
-
- /**
- * The options to pass to all test runner invocation command lines.
- *
- * @parameter
- */
- private String[] testrunneroptions;
-
- /**
- * Implementation of the tktest goal.
- */
- public void execute()
- {
- // Skip these tests if test skipping is turned on.
- if (skip)
- {
- getLog().info("Skipping Tests.");
-
- return;
- }
-
- // Log out the classpath if debugging is on.
- if (getLog().isDebugEnabled())
- {
- getLog().info("Test Classpath :");
-
- for (Object classpathElement1 : classpathElements)
- {
- String classpathElement = (String) classpathElement1;
- getLog().info(" " + classpathElement);
- }
- }
-
- try
- {
- // Create a class loader to load the test runner with. This also gets set as the context loader for this
- // thread, so that all subsequent class loading activity by the test runner or the test code, has the
- // test classes available to it. The system loader is set up for the maven build, which is why a seperate
- // loader needs to be created; in order to inject the test dependencies into it.
- ClassLoader runnerClassLoader = createClassLoader(classpathElements, ClassLoader.getSystemClassLoader(), true);
- Thread.currentThread().setContextClassLoader(runnerClassLoader);
-
- // Load the test runner implementation that will be used to run the tests.
- if ((testrunner == null) || "".equals(testrunner))
- {
- testrunner = "org.apache.qpid.junit.extensions.TKTestRunner";
- }
-
- Class testRunnerClass = Class.forName(testrunner, false, runnerClassLoader);
- Method run = testRunnerClass.getMethod("main", String[].class);
-
- // Concatenate all of the options to pass on the command line to the test runner.
- String preOptions = "";
-
- for (String option : testrunneroptions)
- {
- preOptions += option + " ";
- }
-
- // Concatenate all of the additional properties as name=value pairs on the command line.
- String nvPairs = "";
-
- if (testrunnerproperties != null)
- {
- for (Object objKey : testrunnerproperties.keySet())
- {
- String key = (String) objKey;
- String value = testrunnerproperties.getProperty(key);
-
- nvPairs = key + "=" + value + " ";
- }
- }
-
- // Pass each of the test runner command lines in turn to the toolkit test runner.
- // The command line is made up of the options, the command specific command line, then the trailing
- // name=value pairs.
- for (String testName : commands.keySet())
- {
- String commandLine = preOptions + " " + commands.get(testName) + " " + nvPairs;
- getLog().info("commandLine = " + commandLine);
-
- // Tokenize the command line on white space, into an array of string components.
- String[] tokenizedCommandLine = commandLine.split("\\s+");
-
- // Run the tests.
- run.invoke(testRunnerClass, new Object[] { tokenizedCommandLine });
- }
- }
- catch (Exception e)
- {
- getLog().error("There was an exception: " + e.getMessage(), e);
- }
- }
-
- private static ClassLoader createClassLoader(List classPathUrls, ClassLoader parent, boolean childDelegation)
- throws MalformedURLException
- {
- List urls = new ArrayList();
-
- for (Iterator i = classPathUrls.iterator(); i.hasNext();)
- {
- String url = (String) i.next();
-
- if (url != null)
- {
- File f = new File(url);
- urls.add(f.toURL());
- }
- }
-
- IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation);
-
- for (Iterator iter = urls.iterator(); iter.hasNext();)
- {
- URL url = (URL) iter.next();
- classLoader.addURL(url);
- }
-
- return classLoader;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.maven;
+
+import org.apache.maven.plugin.AbstractMojo;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * TKTestRunnerMojo is a JUnit test runner plugin for Maven 2. It is intended to be compatible with the surefire
+ * plugin (though not all features of that are yet implemented), with some extended capabilities.
+ *
+ * <p/>This plugin adds the ability to use different JUnit test runners, and to pass arbitrary options to them.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @author Rupert Smith
+ *
+ * @goal tktest
+ * @phase test
+ * @requiresDependencyResolution test
+ */
+public class TKTestRunnerMojo extends AbstractMojo
+{
+ private static final BitSet UNRESERVED = new BitSet(256);
+
+ /**
+ * Set this to 'true' to bypass unit tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.
+ *
+ * @parameter expression="${maven.test.skip}"
+ */
+ private boolean skip;
+
+ /**
+ * The TKTest runner command lines. There are passed directly to the TKTestRunner main method.
+ *
+ * @parameter
+ */
+ private Map<String, String> commands = new LinkedHashMap<String, String>();
+
+ /**
+ * The base directory of the project being tested. This can be obtained in your unit test by
+ * System.getProperty("basedir").
+ *
+ * @parameter expression="${basedir}"
+ * @required
+ */
+ private File basedir;
+
+ /**
+ * The directory containing generated classes of the project being tested.
+ *
+ * @parameter expression="${project.build.outputDirectory}"
+ * @required
+ */
+ private File classesDirectory;
+
+ /**
+ * The directory containing generated test classes of the project being tested.
+ *
+ * @parameter expression="${project.build.testOutputDirectory}"
+ * @required
+ */
+ private File testClassesDirectory;
+
+ /**
+ * The classpath elements of the project being tested.
+ *
+ * @parameter expression="${project.testClasspathElements}"
+ * @required
+ * @readonly
+ */
+ private List classpathElements;
+
+ /**
+ * List of System properties to pass to the tests.
+ *
+ * @parameter
+ */
+ private Properties systemProperties;
+
+ /**
+ * Map of of plugin artifacts.
+ *
+ * @parameter expression="${plugin.artifactMap}"
+ * @required
+ * @readonly
+ */
+ private Map pluginArtifactMap;
+
+ /**
+ * Map of of project artifacts.
+ *
+ * @parameter expression="${project.artifactMap}"
+ * @required
+ * @readonly
+ */
+ private Map projectArtifactMap;
+
+ /**
+ * Option to specify the forking mode. Can be "never" (default), "once" or "always".
+ * "none" and "pertest" are also accepted for backwards compatibility.
+ *
+ * @parameter expression="${forkMode}" default-value="once"
+ */
+ private String forkMode;
+
+ /**
+ * Option to specify the jvm (or path to the java executable) to use with
+ * the forking options. For the default we will assume that java is in the path.
+ *
+ * @parameter expression="${jvm}"
+ * default-value="java"
+ */
+ private String jvm;
+
+ /**
+ * The test runner to use.
+ *
+ * @parameter
+ */
+ private String testrunner;
+
+ /**
+ * The additional properties to append to the test runner invocation command line.
+ *
+ * @parameter
+ */
+ private Properties testrunnerproperties;
+
+ /**
+ * The options to pass to all test runner invocation command lines.
+ *
+ * @parameter
+ */
+ private String[] testrunneroptions;
+
+ /**
+ * Implementation of the tktest goal.
+ */
+ public void execute()
+ {
+ // Skip these tests if test skipping is turned on.
+ if (skip)
+ {
+ getLog().info("Skipping Tests.");
+
+ return;
+ }
+
+ // Log out the classpath if debugging is on.
+ if (getLog().isDebugEnabled())
+ {
+ getLog().info("Test Classpath :");
+
+ for (Object classpathElement1 : classpathElements)
+ {
+ String classpathElement = (String) classpathElement1;
+ getLog().info(" " + classpathElement);
+ }
+ }
+
+ try
+ {
+ // Create a class loader to load the test runner with. This also gets set as the context loader for this
+ // thread, so that all subsequent class loading activity by the test runner or the test code, has the
+ // test classes available to it. The system loader is set up for the maven build, which is why a seperate
+ // loader needs to be created; in order to inject the test dependencies into it.
+ ClassLoader runnerClassLoader = createClassLoader(classpathElements, ClassLoader.getSystemClassLoader(), true);
+ Thread.currentThread().setContextClassLoader(runnerClassLoader);
+
+ // Load the test runner implementation that will be used to run the tests.
+ if ((testrunner == null) || "".equals(testrunner))
+ {
+ testrunner = "org.apache.qpid.junit.extensions.TKTestRunner";
+ }
+
+ Class testRunnerClass = Class.forName(testrunner, false, runnerClassLoader);
+ Method run = testRunnerClass.getMethod("main", String[].class);
+
+ // Concatenate all of the options to pass on the command line to the test runner.
+ String preOptions = "";
+
+ for (String option : testrunneroptions)
+ {
+ preOptions += option + " ";
+ }
+
+ // Concatenate all of the additional properties as name=value pairs on the command line.
+ String nvPairs = "";
+
+ if (testrunnerproperties != null)
+ {
+ for (Object objKey : testrunnerproperties.keySet())
+ {
+ String key = (String) objKey;
+ String value = testrunnerproperties.getProperty(key);
+
+ nvPairs = key + "=" + value + " ";
+ }
+ }
+
+ // Pass each of the test runner command lines in turn to the toolkit test runner.
+ // The command line is made up of the options, the command specific command line, then the trailing
+ // name=value pairs.
+ for (String testName : commands.keySet())
+ {
+ String commandLine = preOptions + " " + commands.get(testName) + " " + nvPairs;
+ getLog().info("commandLine = " + commandLine);
+
+ // Tokenize the command line on white space, into an array of string components.
+ String[] tokenizedCommandLine = commandLine.split("\\s+");
+
+ // Run the tests.
+ run.invoke(testRunnerClass, new Object[] { tokenizedCommandLine });
+ }
+ }
+ catch (Exception e)
+ {
+ getLog().error("There was an exception: " + e.getMessage(), e);
+ }
+ }
+
+ private static ClassLoader createClassLoader(List classPathUrls, ClassLoader parent, boolean childDelegation)
+ throws MalformedURLException
+ {
+ List urls = new ArrayList();
+
+ for (Iterator i = classPathUrls.iterator(); i.hasNext();)
+ {
+ String url = (String) i.next();
+
+ if (url != null)
+ {
+ File f = new File(url);
+ urls.add(f.toURL());
+ }
+ }
+
+ IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation);
+
+ for (Iterator iter = urls.iterator(); iter.hasNext();)
+ {
+ URL url = (URL) iter.next();
+ classLoader.addURL(url);
+ }
+
+ return classLoader;
+ }
+}
diff --git a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java
index 5c7669e069..adbe527e5e 100644
--- a/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java
+++ b/qpid/java/junit-toolkit-maven-plugin/src/main/org/apache/qpid/junit/maven/TKTestScriptGenMojo.java
@@ -1,148 +1,148 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.maven;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- * @goal tkscriptgen
- * @phase test
- * @execute phase="test"
- * @requiresDependencyResolution test
- */
-public class TKTestScriptGenMojo extends AbstractMojo
-{
- private static final String _scriptLanguage = "#!/bin/bash\n\n";
-
- private static final String _javaOptArgParser =
- "# Parse arguements taking all - prefixed args as JAVA_OPTS\n" + "for arg in \"$@\"; do\n"
- + " if [[ $arg == -java:* ]]; then\n" + " JAVA_OPTS=\"${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` \"\n"
- + " else\n" + " ARGS=\"${ARGS}$arg \"\n" + " fi\n" + "done\n\n";
-
- /**
- * Where to write out the scripts.
- *
- * @parameter
- */
- private String scriptOutDirectory;
-
- /**
- * The all-in-one test jar location.
- *
- * @parameter
- */
- private String testJar;
-
- /**
- * The system properties to pass to java runtime.
- *
- * @parameter
- */
- private Properties systemproperties;
-
- /**
- * The TKTest runner command lines. There are passed directly to the TKTestRunner main method.
- *
- * @parameter
- */
- private Map<String, String> commands = new LinkedHashMap<String, String>();
-
- /**
- * Implementation of the tkscriptgen goal.
- *
- * @throws MojoExecutionException
- */
- public void execute() throws MojoExecutionException
- {
- // Turn each of the test runner command lines into a script.
- for (String testName : commands.keySet())
- {
- String testOptions = commands.get(testName);
- String commandLine = "java ";
-
- String logdir = null;
-
- for (Object key : systemproperties.keySet())
- {
- String keyString = (String) key;
- String value = systemproperties.getProperty(keyString);
-
- if (keyString.equals("logdir"))
- {
- logdir = value;
- }
- else
- {
- if (keyString.startsWith("-X"))
- {
- commandLine += keyString + value + " ";
- }
- else
- {
- commandLine += "-D" + keyString + "=" + value + " ";
- }
- }
- }
-
- commandLine +=
- "${JAVA_OPTS} -cp " + testJar + " org.apache.qpid.junit.extensions.TKTestRunner " + testOptions + " ${ARGS}";
-
- getLog().info("Generating Script for test: " + testName);
- getLog().debug(commandLine);
-
- String fileName = scriptOutDirectory + "/" + testName + ".sh";
-
- try
- {
- File scriptFile = new File(fileName);
- Writer scriptWriter = new FileWriter(scriptFile);
- scriptWriter.write(_scriptLanguage);
- scriptWriter.write(_javaOptArgParser);
- if (logdir != null)
- {
- scriptWriter.write("mkdir -p " + logdir + "\n");
- }
-
- scriptWriter.write(commandLine);
- scriptWriter.flush();
- scriptWriter.close();
- }
- catch (IOException e)
- {
- getLog().error("Failed to write: " + fileName);
- }
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.maven;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @author Rupert Smith
+ * @goal tkscriptgen
+ * @phase test
+ * @execute phase="test"
+ * @requiresDependencyResolution test
+ */
+public class TKTestScriptGenMojo extends AbstractMojo
+{
+ private static final String _scriptLanguage = "#!/bin/bash\n\n";
+
+ private static final String _javaOptArgParser =
+ "# Parse arguements taking all - prefixed args as JAVA_OPTS\n" + "for arg in \"$@\"; do\n"
+ + " if [[ $arg == -java:* ]]; then\n" + " JAVA_OPTS=\"${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` \"\n"
+ + " else\n" + " ARGS=\"${ARGS}$arg \"\n" + " fi\n" + "done\n\n";
+
+ /**
+ * Where to write out the scripts.
+ *
+ * @parameter
+ */
+ private String scriptOutDirectory;
+
+ /**
+ * The all-in-one test jar location.
+ *
+ * @parameter
+ */
+ private String testJar;
+
+ /**
+ * The system properties to pass to java runtime.
+ *
+ * @parameter
+ */
+ private Properties systemproperties;
+
+ /**
+ * The TKTest runner command lines. There are passed directly to the TKTestRunner main method.
+ *
+ * @parameter
+ */
+ private Map<String, String> commands = new LinkedHashMap<String, String>();
+
+ /**
+ * Implementation of the tkscriptgen goal.
+ *
+ * @throws MojoExecutionException
+ */
+ public void execute() throws MojoExecutionException
+ {
+ // Turn each of the test runner command lines into a script.
+ for (String testName : commands.keySet())
+ {
+ String testOptions = commands.get(testName);
+ String commandLine = "java ";
+
+ String logdir = null;
+
+ for (Object key : systemproperties.keySet())
+ {
+ String keyString = (String) key;
+ String value = systemproperties.getProperty(keyString);
+
+ if (keyString.equals("logdir"))
+ {
+ logdir = value;
+ }
+ else
+ {
+ if (keyString.startsWith("-X"))
+ {
+ commandLine += keyString + value + " ";
+ }
+ else
+ {
+ commandLine += "-D" + keyString + "=" + value + " ";
+ }
+ }
+ }
+
+ commandLine +=
+ "${JAVA_OPTS} -cp " + testJar + " org.apache.qpid.junit.extensions.TKTestRunner " + testOptions + " ${ARGS}";
+
+ getLog().info("Generating Script for test: " + testName);
+ getLog().debug(commandLine);
+
+ String fileName = scriptOutDirectory + "/" + testName + ".sh";
+
+ try
+ {
+ File scriptFile = new File(fileName);
+ Writer scriptWriter = new FileWriter(scriptFile);
+ scriptWriter.write(_scriptLanguage);
+ scriptWriter.write(_javaOptArgParser);
+ if (logdir != null)
+ {
+ scriptWriter.write("mkdir -p " + logdir + "\n");
+ }
+
+ scriptWriter.write(commandLine);
+ scriptWriter.flush();
+ scriptWriter.close();
+ }
+ catch (IOException e)
+ {
+ getLog().error("Failed to write: " + fileName);
+ }
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java
index 6c88d019c4..8fb0a6a90e 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/DefaultThreadFactory.java
@@ -1,48 +1,48 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.concurrency;
-
-import java.util.concurrent.ThreadFactory;
-
-/**
- * Implements a default thread factory.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Create default threads with no specialization.
- * </table>
- *
- * @author Rupert Smith
- */
-public class DefaultThreadFactory implements ThreadFactory
-{
- /**
- * Constructs a new <tt>Thread</tt>.
- *
- * @param r A runnable to be executed by new thread instance.
- *
- * @return The constructed thread.
- */
- public Thread newThread(Runnable r)
- {
- return new Thread(r);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.concurrency;
+
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Implements a default thread factory.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create default threads with no specialization.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class DefaultThreadFactory implements ThreadFactory
+{
+ /**
+ * Constructs a new <tt>Thread</tt>.
+ *
+ * @param r A runnable to be executed by new thread instance.
+ *
+ * @return The constructed thread.
+ */
+ public Thread newThread(Runnable r)
+ {
+ return new Thread(r);
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java
index 0bb07a4557..3bbfc2d502 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/PossibleDeadlockException.java
@@ -1,46 +1,46 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.concurrency;
-
-/**
- * PossibleDeadlockException is used to signal that two test threads being executed by a {@link ThreadTestCoordinator}
- * may be in a state of deadlock because they are mutually blocking each other or one is waiting on the other and the
- * other has been blocked elsewhere for longer than a specified timeout.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Signal a possible state of deadlock between coordinated test threads.
- * </table>
- *
- * @author Rupert Smith
- */
-public class PossibleDeadlockException extends RuntimeException
-{
- /**
- * Create a new possible deadlock execption.
- *
- * @param message The exception message.
- */
- public PossibleDeadlockException(String message)
- {
- super(message);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.concurrency;
+
+/**
+ * PossibleDeadlockException is used to signal that two test threads being executed by a {@link ThreadTestCoordinator}
+ * may be in a state of deadlock because they are mutually blocking each other or one is waiting on the other and the
+ * other has been blocked elsewhere for longer than a specified timeout.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Signal a possible state of deadlock between coordinated test threads.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class PossibleDeadlockException extends RuntimeException
+{
+ /**
+ * Create a new possible deadlock execption.
+ *
+ * @param message The exception message.
+ */
+ public PossibleDeadlockException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java
index 5bf0c430cd..02e776a4ea 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/TestRunnable.java
@@ -1,239 +1,239 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.concurrency;
-
-/**
- * TestRunnable is an extension of java.util.Runnable that adds some features to make it easier to coordinate the
- * activities of threads in such a way as to expose bugs in multi threaded code.
- *
- * <p/>Sometimes several threads will run in a particular order so that a bug is not revealed. Other times the ordering
- * of the threads will expose a bug. Such bugs can be hard to replicate as the exact execution ordering of threads is not
- * usually controlled. This class adds some methods that allow threads to synchronize other threads, either allowing them
- * to run, or waiting for them to allow this thread to run. It also provides convenience methods to gather error messages
- * and exceptions from threads, which will often be reported in unit testing code.
- *
- * <p/>Coordination between threads is handled by the {@link ThreadTestCoordinator}. It is called through the convenience
- * methods {@link #allow} and {@link #waitFor}. Threads to be coordinated must be set up with the coordinator and assigned
- * integer ids. It is then possible to call the coordinator with an array of thread ids requesting that those threads
- * be allowed to continue, or to wait until one of them allows this thread to continue. The otherwise non-deterministic
- * execution order of threads can be controlled into a carefully determined sequence using these methods in order
- * to reproduce race conditions, dead locks, live locks, dirty reads, phantom reads, non repeatable reads and so on.
- *
- * <p/>When waiting for another thread to give a signal to continue it is sometimes the case that the other thread has
- * become blocked by the code under test. For example in testing for a dirty read (for example in database code),
- * thread 1 lets thread 2 perform a write but not commit it, then thread 2 lets thread 1 run and attempt to perform a
- * dirty read on its uncommitted write. Transaction synchronization code being tested against the possibility of a dirty
- * write may make use of snapshots in which case both threads should be able to read and write without blocking. It may
- * make use of explicit keys in which case thread 2 may become blocked on its write attempt because thread 1 holds a
- * read lock and it must wait until thread 1 completes its transaction before it can acquire this lock. The
- * {@link #waitFor} method accepts a boolean parameter to indicate that threads being blocked (other than on the
- * coordinator) can be interpreted the same as if the thread explicitly allows the thread calling waitFor to continue.
- * Using this technique a dirty read test could be written that works against either the snapshot or the locking
- * implementation, allowing both approaches to pass the test yet arranging for multiple threads to run against the
- * implementation in such a way that a potential dirty read bug is exposed.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Wait for another thread to allow this one to continue.
- * <tr><td> Allow another thread to continue.
- * <tr><td> Accumulate error messages.
- * <tr><td> Record exceptions from thread run.
- * <tr><td> Maintain link to thread coordinator.
- * <tr><td> Explicitly mark a thread with an integer id.
- * <tr><td> Maintian a flag to indicate whether or not this thread is waiting on the coordinator.
- * </table>
- *
- * @todo The allow then waitFor operations are very often used as a pair. So create a method allowAndWait that combines
- * them into a single method call.
- *
- * @author Rupert Smith
- */
-public abstract class TestRunnable implements Runnable
-{
- /** Holds a reference to the thread coordinator. */
- private ThreadTestCoordinator coordinator;
-
- /** Holds the explicit integer id of this thread. */
- private int id;
-
- /** Used to indicate that this thread is waiting on the coordinator and not elsewhere. */
- private boolean waitingOnCoordinator = false;
-
- /** Used to accumulate error messsages. */
- private String errorMessage = "";
-
- /** Holds the Java thread object that this is running under. */
- private Thread thisThread;
-
- /** Used to hold any exceptions resulting from the run method. */
- private Exception runException = null;
-
- /**
- * Implementations override this to perform coordinated thread sequencing.
- *
- * @throws Exception Any exception raised by the implementation will be caught by the default {@link #run()}
- * implementation for later querying by the {@link #getException()} method.
- */
- public abstract void runWithExceptions() throws Exception;
-
- /**
- * Provides a default implementation of the run method that allows exceptions to be thrown and keeps a record
- * of those exceptions. Defers to the {@link #runWithExceptions()} method to provide the thread body implementation
- * and catches any exceptions thrown by it.
- */
- public void run()
- {
- try
- {
- runWithExceptions();
- }
- catch (Exception e)
- {
- this.runException = e;
- }
- }
-
- /**
- * Attempt to consume an allow event from one of the specified threads and blocks until such an event occurrs.
- *
- * @param threads The set of threads that can allow this one to continue.
- * @param otherWaitIsAllow If set to <tt>true</tt> if the threads being waited on are blocked other than on
- * the coordinator itself then this is to be interpreted as allowing this thread to
- * continue.
- *
- * @return If the <tt>otherWaitIsAllow</tt> flag is set, then <tt>true</tt> is returned when the thread being waited on is found
- * to be blocked outside of the thread test coordinator. <tt>false</tt> under all other conditions.
- */
- protected boolean waitFor(int[] threads, boolean otherWaitIsAllow)
- {
- return coordinator.consumeAllowEvent(threads, otherWaitIsAllow, id, this);
- }
-
- /**
- * Produces allow events on each of the specified threads.
- *
- * @param threads The set of threads that are to be allowed to continue.
- */
- protected void allow(int[] threads)
- {
- coordinator.produceAllowEvents(threads, id, this);
- }
-
- /**
- * Keeps the error message for later reporting by the coordinator.
- *
- * @param message The error message to keep.
- */
- protected void addErrorMessage(String message)
- {
- errorMessage += message;
- }
-
- /**
- * Sets the coordinator for this thread.
- *
- * @param coordinator The coordinator for this thread.
- */
- void setCoordinator(ThreadTestCoordinator coordinator)
- {
- this.coordinator = coordinator;
- }
-
- /**
- * Reports whether or not this thread is waiting on the coordinator.
- *
- * @return <tt>If this thread is waiting on the coordinator.
- */
- boolean isWaitingOnCoordinator()
- {
- return waitingOnCoordinator;
- }
-
- /**
- * Sets the value of the waiting on coordinator flag.
- *
- * @param waiting The value of the waiting on coordinator flag.
- */
- void setWaitingOnCoordinator(boolean waiting)
- {
- waitingOnCoordinator = waiting;
- }
-
- /**
- * Sets up the explicit int id for this thread.
- *
- * @param id The integer id.
- */
- void setId(int id)
- {
- this.id = id;
- }
-
- /**
- * Reports any accumulated error messages.
- *
- * @return Any accumulated error messages.
- */
- String getErrorMessage()
- {
- return errorMessage;
- }
-
- /**
- * Reports any exception thrown by the {@link #runWithExceptions} method.
- *
- * @return Any exception thrown by the {@link #runWithExceptions} method.
- */
- Exception getException()
- {
- return runException;
- }
-
- /**
- * Sets the Java thread under which this runs.
- *
- * @param thread The Java thread under which this runs.
- */
- void setThread(Thread thread)
- {
- thisThread = thread;
- }
-
- /**
- * Gets the Java thread under which this runs.
- *
- * @return The Java thread under which this runs.
- */
- Thread getThread()
- {
- return thisThread;
- }
-
- /**
- * Provides a string summary of this test threads status.
- *
- * @return Summarizes this threads status.
- */
- public String toString()
- {
- return "id = " + id + ", waitingOnCoordinator = " + waitingOnCoordinator;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.concurrency;
+
+/**
+ * TestRunnable is an extension of java.util.Runnable that adds some features to make it easier to coordinate the
+ * activities of threads in such a way as to expose bugs in multi threaded code.
+ *
+ * <p/>Sometimes several threads will run in a particular order so that a bug is not revealed. Other times the ordering
+ * of the threads will expose a bug. Such bugs can be hard to replicate as the exact execution ordering of threads is not
+ * usually controlled. This class adds some methods that allow threads to synchronize other threads, either allowing them
+ * to run, or waiting for them to allow this thread to run. It also provides convenience methods to gather error messages
+ * and exceptions from threads, which will often be reported in unit testing code.
+ *
+ * <p/>Coordination between threads is handled by the {@link ThreadTestCoordinator}. It is called through the convenience
+ * methods {@link #allow} and {@link #waitFor}. Threads to be coordinated must be set up with the coordinator and assigned
+ * integer ids. It is then possible to call the coordinator with an array of thread ids requesting that those threads
+ * be allowed to continue, or to wait until one of them allows this thread to continue. The otherwise non-deterministic
+ * execution order of threads can be controlled into a carefully determined sequence using these methods in order
+ * to reproduce race conditions, dead locks, live locks, dirty reads, phantom reads, non repeatable reads and so on.
+ *
+ * <p/>When waiting for another thread to give a signal to continue it is sometimes the case that the other thread has
+ * become blocked by the code under test. For example in testing for a dirty read (for example in database code),
+ * thread 1 lets thread 2 perform a write but not commit it, then thread 2 lets thread 1 run and attempt to perform a
+ * dirty read on its uncommitted write. Transaction synchronization code being tested against the possibility of a dirty
+ * write may make use of snapshots in which case both threads should be able to read and write without blocking. It may
+ * make use of explicit keys in which case thread 2 may become blocked on its write attempt because thread 1 holds a
+ * read lock and it must wait until thread 1 completes its transaction before it can acquire this lock. The
+ * {@link #waitFor} method accepts a boolean parameter to indicate that threads being blocked (other than on the
+ * coordinator) can be interpreted the same as if the thread explicitly allows the thread calling waitFor to continue.
+ * Using this technique a dirty read test could be written that works against either the snapshot or the locking
+ * implementation, allowing both approaches to pass the test yet arranging for multiple threads to run against the
+ * implementation in such a way that a potential dirty read bug is exposed.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Wait for another thread to allow this one to continue.
+ * <tr><td> Allow another thread to continue.
+ * <tr><td> Accumulate error messages.
+ * <tr><td> Record exceptions from thread run.
+ * <tr><td> Maintain link to thread coordinator.
+ * <tr><td> Explicitly mark a thread with an integer id.
+ * <tr><td> Maintian a flag to indicate whether or not this thread is waiting on the coordinator.
+ * </table>
+ *
+ * @todo The allow then waitFor operations are very often used as a pair. So create a method allowAndWait that combines
+ * them into a single method call.
+ *
+ * @author Rupert Smith
+ */
+public abstract class TestRunnable implements Runnable
+{
+ /** Holds a reference to the thread coordinator. */
+ private ThreadTestCoordinator coordinator;
+
+ /** Holds the explicit integer id of this thread. */
+ private int id;
+
+ /** Used to indicate that this thread is waiting on the coordinator and not elsewhere. */
+ private boolean waitingOnCoordinator = false;
+
+ /** Used to accumulate error messsages. */
+ private String errorMessage = "";
+
+ /** Holds the Java thread object that this is running under. */
+ private Thread thisThread;
+
+ /** Used to hold any exceptions resulting from the run method. */
+ private Exception runException = null;
+
+ /**
+ * Implementations override this to perform coordinated thread sequencing.
+ *
+ * @throws Exception Any exception raised by the implementation will be caught by the default {@link #run()}
+ * implementation for later querying by the {@link #getException()} method.
+ */
+ public abstract void runWithExceptions() throws Exception;
+
+ /**
+ * Provides a default implementation of the run method that allows exceptions to be thrown and keeps a record
+ * of those exceptions. Defers to the {@link #runWithExceptions()} method to provide the thread body implementation
+ * and catches any exceptions thrown by it.
+ */
+ public void run()
+ {
+ try
+ {
+ runWithExceptions();
+ }
+ catch (Exception e)
+ {
+ this.runException = e;
+ }
+ }
+
+ /**
+ * Attempt to consume an allow event from one of the specified threads and blocks until such an event occurrs.
+ *
+ * @param threads The set of threads that can allow this one to continue.
+ * @param otherWaitIsAllow If set to <tt>true</tt> if the threads being waited on are blocked other than on
+ * the coordinator itself then this is to be interpreted as allowing this thread to
+ * continue.
+ *
+ * @return If the <tt>otherWaitIsAllow</tt> flag is set, then <tt>true</tt> is returned when the thread being waited on is found
+ * to be blocked outside of the thread test coordinator. <tt>false</tt> under all other conditions.
+ */
+ protected boolean waitFor(int[] threads, boolean otherWaitIsAllow)
+ {
+ return coordinator.consumeAllowEvent(threads, otherWaitIsAllow, id, this);
+ }
+
+ /**
+ * Produces allow events on each of the specified threads.
+ *
+ * @param threads The set of threads that are to be allowed to continue.
+ */
+ protected void allow(int[] threads)
+ {
+ coordinator.produceAllowEvents(threads, id, this);
+ }
+
+ /**
+ * Keeps the error message for later reporting by the coordinator.
+ *
+ * @param message The error message to keep.
+ */
+ protected void addErrorMessage(String message)
+ {
+ errorMessage += message;
+ }
+
+ /**
+ * Sets the coordinator for this thread.
+ *
+ * @param coordinator The coordinator for this thread.
+ */
+ void setCoordinator(ThreadTestCoordinator coordinator)
+ {
+ this.coordinator = coordinator;
+ }
+
+ /**
+ * Reports whether or not this thread is waiting on the coordinator.
+ *
+ * @return <tt>If this thread is waiting on the coordinator.
+ */
+ boolean isWaitingOnCoordinator()
+ {
+ return waitingOnCoordinator;
+ }
+
+ /**
+ * Sets the value of the waiting on coordinator flag.
+ *
+ * @param waiting The value of the waiting on coordinator flag.
+ */
+ void setWaitingOnCoordinator(boolean waiting)
+ {
+ waitingOnCoordinator = waiting;
+ }
+
+ /**
+ * Sets up the explicit int id for this thread.
+ *
+ * @param id The integer id.
+ */
+ void setId(int id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * Reports any accumulated error messages.
+ *
+ * @return Any accumulated error messages.
+ */
+ String getErrorMessage()
+ {
+ return errorMessage;
+ }
+
+ /**
+ * Reports any exception thrown by the {@link #runWithExceptions} method.
+ *
+ * @return Any exception thrown by the {@link #runWithExceptions} method.
+ */
+ Exception getException()
+ {
+ return runException;
+ }
+
+ /**
+ * Sets the Java thread under which this runs.
+ *
+ * @param thread The Java thread under which this runs.
+ */
+ void setThread(Thread thread)
+ {
+ thisThread = thread;
+ }
+
+ /**
+ * Gets the Java thread under which this runs.
+ *
+ * @return The Java thread under which this runs.
+ */
+ Thread getThread()
+ {
+ return thisThread;
+ }
+
+ /**
+ * Provides a string summary of this test threads status.
+ *
+ * @return Summarizes this threads status.
+ */
+ public String toString()
+ {
+ return "id = " + id + ", waitingOnCoordinator = " + waitingOnCoordinator;
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
index 0be0fe37dc..605c35feed 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestCoordinator.java
@@ -1,485 +1,485 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.concurrency;
-
-import org.apache.log4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.ThreadFactory;
-
-/**
- * ThreadTestCoordinator provides an array of binary latches that allows threads to wait for other threads or to send
- * them a signal that allows them to continue running or to wait for another thread to signal them. The binary latch
- * array is always a square array, allowing one latch from and to every thread. Upon accepting an allow signal from one
- * sender the latches for all senders for a are cleared. This class is always used in conjunction with
- * {@link TestRunnable} for writing concurrent test code that coordinates multi-threaded activity in order to reproduce
- * concurrency bugs.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept test threads to coordinate.
- * <tr><td> Allow test threads to send 'allow to continue' signals.
- * <tr><td> Allow test threads to wait on this coordinator for 'allow to continue' signals.
- * <tr><td> Report error messages from test threads.
- * <tr><td> Report exceptions from test threads.
- * <tr><td> Provide method to wait until all test threads have completed.
- * </table>
- *
- * @todo This code was hacked together as a bit of an experiment, because I wasn't sure if this idea would work. It has
- * proved extremely usefull. Some documentation for this needs to be written to explain it better.
- *
- * @todo Consider how deadlock detection will be handled. If all threads are blocking on the coordinator, waiting for
- * each other, they are deadlocked and there is something wrong with the test code that put them in that
- * situation. If they are all blocked elsewhere, they may be deadlocked, or could just be waiting on some
- * external event. A timeout should be used. Timeout is already implemented, just need to sanity check how
- * this is working and document it.
- *
- * @todo Consider how livelock detection could be implemented? LockFree data structures might cause live locks. I
- * guess a longish timeout is the only thing that can be done for that.
- *
- * @todo Only course grained synchronous at the method class level can be obtained. This is because test code can
- * only insert synchronization points between method calls it makes. So this code will not be usefull for
- * checking sequences of events within methods, unless the code under test is explicitly instrumented for it.
- * It might be possible to instrument code by using labels, and then use the debugger/profiler interface to
- * put breakpoints on the labels and use them as synchronization points. Not perfect, but at the unused labels
- * can be left in the code, without altering its behaviour.
- *
- * @author Rupert Smith
- */
-public class ThreadTestCoordinator
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(ThreadTestCoordinator.class);
-
- /** Keeps track of the test threads by their ids. */
- private TestRunnable[] testThreads; // = new TestRunnable[2];
-
- /** An explicit thread monitor for the coordinator. Threads wait on the coordinator whilst waiting for events. */
- private final Object coordinatorLock = new Object();
-
- /** A set of monitors for each test thread. */
- private Object[] locks;
-
- /** The binary latch array, this is always a square array allowing one event from and to every thread. */
- private boolean[][] allowEvents;
-
- /** Keeps track of the number of threads being coordinated. */
- private int threadCount = 0;
-
- /** Accumulates any exceptions resulting from the threads run methods. */
- private Collection<Exception> exceptions = new ArrayList<Exception>();
-
- /**
- * Holds the deadlock timeout after which threads are given a runtime exception to signal that a potential
- * deadlock may be happening.
- */
- private long deadlockTimeout = 1000 * 1000000;
-
- /** Holds the factory to create test thread with. */
- private ThreadFactory threadFactory;
-
- /**
- * Creates a new test thread coordinator. The number of threads to run must be specified here.
- *
- * @param numThreads The number of threads to run.
- */
- public ThreadTestCoordinator(int numThreads)
- {
- this.threadCount = numThreads;
-
- // Create an array big enough to hold all the test threads.
- testThreads = new TestRunnable[threadCount];
-
- // Use the default thread factory, as none specified.
- threadFactory = new DefaultThreadFactory();
- }
-
- /**
- * Creates a new test thread coordinator with a specific thread factory. The number of threads to run must be
- * specified here.
- *
- * @param numThreads The number of threads to run.
- * @param threadFactory The factory to use to create the test threads.
- */
- public ThreadTestCoordinator(int numThreads, ThreadFactory threadFactory)
- {
- this.threadCount = numThreads;
-
- // Create an array big enough to hold all the test threads.
- testThreads = new TestRunnable[threadCount];
-
- // Use the specified thread factory.
- this.threadFactory = threadFactory;
- }
-
- /**
- * Adds a thread to this coordinator and assigns an id to it. The ids must be numbered sequentially from 0 and
- * it is up to the caller to do this.
- *
- * @param runnable The test thread.
- * @param id The explicit id to assign to the test thread.
- */
- public void addTestThread(TestRunnable runnable, int id)
- {
- testThreads[id] = runnable;
- runnable.setCoordinator(this);
- runnable.setId(id);
- }
-
- /**
- * Starts all the coordinated threads running.
- */
- public void run()
- {
- // Create the monitors for each thread.
- locks = new Object[threadCount];
-
- // Create an appropriately sized event queue to allow one event from and to each thread.
- allowEvents = new boolean[threadCount][threadCount];
-
- // Initialize the monitors and clear the event queues.
- for (int i = 0; i < locks.length; i++)
- {
- locks[i] = new Object();
-
- for (int j = 0; j < locks.length; j++)
- {
- allowEvents[i][j] = false;
- }
- }
-
- // Start all the threads running.
- for (TestRunnable nextRunnable : testThreads)
- {
- // Create a Java thread for the test thread.
- Thread newThread = threadFactory.newThread(nextRunnable);
- nextRunnable.setThread(newThread);
-
- // Start it running.
- newThread.start();
- }
- }
-
- /**
- * Waits until all the test threads have completed and returns any accumulated error messages from them. Any
- * exceptions thrown by their run methods are also kept at this point.
- *
- * @return The accumulated error messages from all the threads concatenated together.
- */
- public String joinAndRetrieveMessages()
- {
- // Create an empty error message.
- String errorMessage = "";
-
- // Join all the test threads.
- for (TestRunnable r : testThreads)
- {
- Thread t = r.getThread();
-
- try
- {
- t.join();
- }
- catch (InterruptedException e)
- { }
-
- // Add any accumulated error messages to the return value.
- errorMessage += r.getErrorMessage();
-
- // Keep any exceptions resulting from the threads run method.
- Exception e = r.getException();
-
- if (e != null)
- {
- exceptions.add(e);
- }
- }
-
- return errorMessage;
- }
-
- /**
- * Reports any accumulated exceptions from the test threads run methods. This method must be called after
- * {@link #joinAndRetrieveMessages}.
- *
- * @return Any accumulated exceptions from the test threads run methods. This method must be called after
- */
- public Collection<Exception> getExceptions()
- {
- return exceptions;
- }
-
- /**
- * Sets a timeout to break out of potential deadlocks. If all threads are waiting for other threads to send
- * them continue events for longer than this timeout then the threads are all terminated.
- *
- * @param millis The minimum time to allow to pass before breaking out of any potential deadlocks.
- *
- * @todo This has not been implemented yet. If a potential deadlock happens then the joinAndRetrieveMessages
- * method should throw a PotentialDeadlockException.
- */
- public void setDeadlockTimeout(long millis)
- {
- deadlockTimeout = millis * 1000000;
- }
-
- /**
- * Creates a set of 'allow to continue' events on the event queues of the specified threads.
- *
- * @param threads The set of threads to allow to continue.
- * @param callerId The explicit id of the calling test thread.
- * @param caller The calling test thread.
- */
- void produceAllowEvents(int[] threads, int callerId, TestRunnable caller)
- {
- // Generate some debugging messages. Very usefull to know how thread synchronization is progressing.
- String message = "Thread " + callerId + " is allowing threads [ ";
-
- for (int j = 0; j < threads.length; j++)
- {
- message += threads[j] + ((j < (threads.length - 1)) ? ", " : "");
- }
-
- message += " ] to continue.";
- log.debug(message);
-
- // For each allow event, synchronize on the threads lock then set the event flag to true.
- for (int id : threads)
- {
- // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
- // being blocked at this time.
- caller.setWaitingOnCoordinator(true);
-
- synchronized (locks[id])
- {
- // Release the wating on coordinator flag now that this thread is running again.
- caller.setWaitingOnCoordinator(false);
-
- // Send the allow to continue event to the receiving thread.
- allowEvents[id][callerId] = true;
- }
- }
-
- // Wake up any threads waiting on the coordinator lock to recheck their event queues.
- // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
- // being blocked at this time.
- caller.setWaitingOnCoordinator(true);
-
- synchronized (coordinatorLock)
- {
- // Release the wating on coordinator flag now that this thread is running again.
- caller.setWaitingOnCoordinator(false);
- coordinatorLock.notifyAll();
- }
- }
-
- /**
- * Consumes an 'allow to continue' from one of the specified threads or waits until one is available or in some
- * cases if one of the specified threads is blocked elsewhere to accept that as an 'allow to continue' event.
- *
- * @param threads The set of threads to accept an allow to continue event from.
- * @param otherWaitIsAllow Whether or not to accept threads being blocked elsewhere as permission to continue.
- * @param callerId The explicit id of the calling test thread.
- * @param caller The calling test thread.
- *
- * @return If the <tt>otherWaitIsAllow</tt> flag is set, then <tt>true</tt> is returned when the thread being waited on is found
- * to be blocked outside of the thread test coordinator. <tt>false</tt> under all other conditions.
- */
- boolean consumeAllowEvent(int[] threads, boolean otherWaitIsAllow, int callerId, TestRunnable caller)
- {
- // Generate some debugging messages. Very usefull to know how thread synchronization is progressing.
- String message = "Thread " + callerId + " is requesting threads [ ";
-
- // Record the time at which this method was called. Will be used for breaking out of potential deadlocks.
- long startTime = System.nanoTime();
-
- for (int j = 0; j < threads.length; j++)
- {
- message += threads[j] + ((j < (threads.length - 1)) ? ", " : "");
- }
-
- message += " ] to allow it to continue.";
- log.debug(message);
-
- // Loop until an allow to continue event is received.
- while (true)
- {
- // Look at all the allowing thread to see if one has created an event for consumption.
- for (int allowerId : threads)
- {
- // Get the threads lock for the event to consume.
- // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
- // being blocked at this time.
- caller.setWaitingOnCoordinator(true);
-
- synchronized (locks[callerId])
- {
- // Release the wating on coordinator flag now that this thread is running again.
- caller.setWaitingOnCoordinator(false);
-
- // Check if there is an event on the queue from the allowing thread to this one.
- if (allowEvents[callerId][allowerId])
- {
- log.debug("Found an allow event, thread " + allowerId + ", is allowing thread " + callerId
- + ", to continue.");
-
- // Consume all the allow events for this thread.
- /*for (int i = 0; i < allowEvents[callerId].length; i++)
- {
- allowEvents[callerId][i] = false;
- }*/
-
- // Consume just the event from the allower to the consumer, leaving other pending allow events alone.
- allowEvents[callerId][allowerId] = false;
-
- return false;
- }
- }
- }
-
- // If waiting elsewhere is to be interpreted as an 'allow to continue' event, then look at the thread status
- // for the threads being waited on to see if any are blocked on other resources.
- if (otherWaitIsAllow)
- {
- log.debug("Other wait is to be interpreted as an allow event.");
-
- // Look at all the potential allower threads.
- for (int allowerId : threads)
- {
- // Get the Java thread state for the allowing thread.
- Thread threadToTest = testThreads[allowerId].getThread();
- Thread.State state = threadToTest.getState();
-
- // Check if the thread is blocked and so a potential candidate for releasing this one.
- if ((state == Thread.State.BLOCKED) || (state == Thread.State.WAITING)
- || (state == Thread.State.TIMED_WAITING))
- {
- log.debug("Found an allower thread, id = " + allowerId + ", that is blocked or wating.");
-
- // Check that the allower thread is not waiting on the coordinator lock or any of the
- // individual thread locks. It must be waiting or blocked on another monitor.
- TestRunnable allowingRunnable = testThreads[allowerId];
- boolean isWaitingOnCoordinator = allowingRunnable.isWaitingOnCoordinator();
-
- if (!isWaitingOnCoordinator)
- {
- log.debug("The allower thread, id = " + allowerId
- + ", is blocked or waiting other than on the coordinator.");
-
- // Get the threads lock for the event to consume.
- caller.setWaitingOnCoordinator(true);
-
- synchronized (locks[callerId])
- {
- caller.setWaitingOnCoordinator(false);
-
- // Consume all the allow events for this thread.
- for (int i = 0; i < allowEvents[callerId].length; i++)
- {
- allowEvents[callerId][i] = false;
- }
-
- return true;
- }
- }
- else
- {
- log.debug("The waiting allower thread, " + allowerId
- + ", is waiting on the coordinator so does not allow thread " + callerId + " to continue.");
- }
- }
- }
- }
-
- // Keep waiting until an 'allow to continue' event can be consumed.
- try
- {
- // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
- // being blocked at this time.
- caller.setWaitingOnCoordinator(true);
-
- synchronized (coordinatorLock)
- {
- // Release the wating on coordinator flag now that this thread is running again.
- caller.setWaitingOnCoordinator(false);
-
- log.debug("Thread " + callerId + " is waiting on coordinator lock for more allow events.");
-
- // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
- // being blocked at this time.
- caller.setWaitingOnCoordinator(true);
- coordinatorLock.wait(10);
- }
- }
- catch (InterruptedException e)
- { }
-
- // Release the waiting on coordinator flag now that this thread is running again.
- caller.setWaitingOnCoordinator(false);
-
- // Check if this thread has been waiting for longer than the deadlock timeout and raise a possible
- // deadlock exception if so.
- long waitTime = System.nanoTime() - startTime;
- log.debug("Thread " + callerId + " has been waiting for " + (waitTime / 1000000) + " milliseconds.");
-
- if (waitTime > deadlockTimeout)
- {
- // Throw a possible deadlock exception.
- throw new PossibleDeadlockException("Possible deadlock due to timeout with state:\n" + this);
- }
-
- log.debug("Thread " + callerId + " has woken up, was waiting for more allow events to become available.");
- }
- }
-
- /**
- * Pretty prints the state of the thread test coordinator, for debugging purposes.
- *
- * @return Pretty printed state of the thread test coordinator.
- */
- public String toString()
- {
- String result = "[";
-
- for (int i = 0; i < allowEvents.length; i++)
- {
- for (int j = 0; j < allowEvents[i].length; j++)
- {
- result += allowEvents[i][j];
-
- result += (j < (allowEvents[i].length - 1)) ? ", " : "";
- }
-
- result += (i < (allowEvents.length - 1)) ? ",\n " : "";
- }
-
- result += "]";
-
- for (int i = 0; i < testThreads.length; i++)
- {
- result += "thread[" + i + "] = " + testThreads[i].toString();
- }
-
- return result;
- }
-
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.concurrency;
+
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * ThreadTestCoordinator provides an array of binary latches that allows threads to wait for other threads or to send
+ * them a signal that allows them to continue running or to wait for another thread to signal them. The binary latch
+ * array is always a square array, allowing one latch from and to every thread. Upon accepting an allow signal from one
+ * sender the latches for all senders for a are cleared. This class is always used in conjunction with
+ * {@link TestRunnable} for writing concurrent test code that coordinates multi-threaded activity in order to reproduce
+ * concurrency bugs.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept test threads to coordinate.
+ * <tr><td> Allow test threads to send 'allow to continue' signals.
+ * <tr><td> Allow test threads to wait on this coordinator for 'allow to continue' signals.
+ * <tr><td> Report error messages from test threads.
+ * <tr><td> Report exceptions from test threads.
+ * <tr><td> Provide method to wait until all test threads have completed.
+ * </table>
+ *
+ * @todo This code was hacked together as a bit of an experiment, because I wasn't sure if this idea would work. It has
+ * proved extremely usefull. Some documentation for this needs to be written to explain it better.
+ *
+ * @todo Consider how deadlock detection will be handled. If all threads are blocking on the coordinator, waiting for
+ * each other, they are deadlocked and there is something wrong with the test code that put them in that
+ * situation. If they are all blocked elsewhere, they may be deadlocked, or could just be waiting on some
+ * external event. A timeout should be used. Timeout is already implemented, just need to sanity check how
+ * this is working and document it.
+ *
+ * @todo Consider how livelock detection could be implemented? LockFree data structures might cause live locks. I
+ * guess a longish timeout is the only thing that can be done for that.
+ *
+ * @todo Only course grained synchronous at the method class level can be obtained. This is because test code can
+ * only insert synchronization points between method calls it makes. So this code will not be usefull for
+ * checking sequences of events within methods, unless the code under test is explicitly instrumented for it.
+ * It might be possible to instrument code by using labels, and then use the debugger/profiler interface to
+ * put breakpoints on the labels and use them as synchronization points. Not perfect, but at the unused labels
+ * can be left in the code, without altering its behaviour.
+ *
+ * @author Rupert Smith
+ */
+public class ThreadTestCoordinator
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(ThreadTestCoordinator.class);
+
+ /** Keeps track of the test threads by their ids. */
+ private TestRunnable[] testThreads; // = new TestRunnable[2];
+
+ /** An explicit thread monitor for the coordinator. Threads wait on the coordinator whilst waiting for events. */
+ private final Object coordinatorLock = new Object();
+
+ /** A set of monitors for each test thread. */
+ private Object[] locks;
+
+ /** The binary latch array, this is always a square array allowing one event from and to every thread. */
+ private boolean[][] allowEvents;
+
+ /** Keeps track of the number of threads being coordinated. */
+ private int threadCount = 0;
+
+ /** Accumulates any exceptions resulting from the threads run methods. */
+ private Collection<Exception> exceptions = new ArrayList<Exception>();
+
+ /**
+ * Holds the deadlock timeout after which threads are given a runtime exception to signal that a potential
+ * deadlock may be happening.
+ */
+ private long deadlockTimeout = 1000 * 1000000;
+
+ /** Holds the factory to create test thread with. */
+ private ThreadFactory threadFactory;
+
+ /**
+ * Creates a new test thread coordinator. The number of threads to run must be specified here.
+ *
+ * @param numThreads The number of threads to run.
+ */
+ public ThreadTestCoordinator(int numThreads)
+ {
+ this.threadCount = numThreads;
+
+ // Create an array big enough to hold all the test threads.
+ testThreads = new TestRunnable[threadCount];
+
+ // Use the default thread factory, as none specified.
+ threadFactory = new DefaultThreadFactory();
+ }
+
+ /**
+ * Creates a new test thread coordinator with a specific thread factory. The number of threads to run must be
+ * specified here.
+ *
+ * @param numThreads The number of threads to run.
+ * @param threadFactory The factory to use to create the test threads.
+ */
+ public ThreadTestCoordinator(int numThreads, ThreadFactory threadFactory)
+ {
+ this.threadCount = numThreads;
+
+ // Create an array big enough to hold all the test threads.
+ testThreads = new TestRunnable[threadCount];
+
+ // Use the specified thread factory.
+ this.threadFactory = threadFactory;
+ }
+
+ /**
+ * Adds a thread to this coordinator and assigns an id to it. The ids must be numbered sequentially from 0 and
+ * it is up to the caller to do this.
+ *
+ * @param runnable The test thread.
+ * @param id The explicit id to assign to the test thread.
+ */
+ public void addTestThread(TestRunnable runnable, int id)
+ {
+ testThreads[id] = runnable;
+ runnable.setCoordinator(this);
+ runnable.setId(id);
+ }
+
+ /**
+ * Starts all the coordinated threads running.
+ */
+ public void run()
+ {
+ // Create the monitors for each thread.
+ locks = new Object[threadCount];
+
+ // Create an appropriately sized event queue to allow one event from and to each thread.
+ allowEvents = new boolean[threadCount][threadCount];
+
+ // Initialize the monitors and clear the event queues.
+ for (int i = 0; i < locks.length; i++)
+ {
+ locks[i] = new Object();
+
+ for (int j = 0; j < locks.length; j++)
+ {
+ allowEvents[i][j] = false;
+ }
+ }
+
+ // Start all the threads running.
+ for (TestRunnable nextRunnable : testThreads)
+ {
+ // Create a Java thread for the test thread.
+ Thread newThread = threadFactory.newThread(nextRunnable);
+ nextRunnable.setThread(newThread);
+
+ // Start it running.
+ newThread.start();
+ }
+ }
+
+ /**
+ * Waits until all the test threads have completed and returns any accumulated error messages from them. Any
+ * exceptions thrown by their run methods are also kept at this point.
+ *
+ * @return The accumulated error messages from all the threads concatenated together.
+ */
+ public String joinAndRetrieveMessages()
+ {
+ // Create an empty error message.
+ String errorMessage = "";
+
+ // Join all the test threads.
+ for (TestRunnable r : testThreads)
+ {
+ Thread t = r.getThread();
+
+ try
+ {
+ t.join();
+ }
+ catch (InterruptedException e)
+ { }
+
+ // Add any accumulated error messages to the return value.
+ errorMessage += r.getErrorMessage();
+
+ // Keep any exceptions resulting from the threads run method.
+ Exception e = r.getException();
+
+ if (e != null)
+ {
+ exceptions.add(e);
+ }
+ }
+
+ return errorMessage;
+ }
+
+ /**
+ * Reports any accumulated exceptions from the test threads run methods. This method must be called after
+ * {@link #joinAndRetrieveMessages}.
+ *
+ * @return Any accumulated exceptions from the test threads run methods. This method must be called after
+ */
+ public Collection<Exception> getExceptions()
+ {
+ return exceptions;
+ }
+
+ /**
+ * Sets a timeout to break out of potential deadlocks. If all threads are waiting for other threads to send
+ * them continue events for longer than this timeout then the threads are all terminated.
+ *
+ * @param millis The minimum time to allow to pass before breaking out of any potential deadlocks.
+ *
+ * @todo This has not been implemented yet. If a potential deadlock happens then the joinAndRetrieveMessages
+ * method should throw a PotentialDeadlockException.
+ */
+ public void setDeadlockTimeout(long millis)
+ {
+ deadlockTimeout = millis * 1000000;
+ }
+
+ /**
+ * Creates a set of 'allow to continue' events on the event queues of the specified threads.
+ *
+ * @param threads The set of threads to allow to continue.
+ * @param callerId The explicit id of the calling test thread.
+ * @param caller The calling test thread.
+ */
+ void produceAllowEvents(int[] threads, int callerId, TestRunnable caller)
+ {
+ // Generate some debugging messages. Very usefull to know how thread synchronization is progressing.
+ String message = "Thread " + callerId + " is allowing threads [ ";
+
+ for (int j = 0; j < threads.length; j++)
+ {
+ message += threads[j] + ((j < (threads.length - 1)) ? ", " : "");
+ }
+
+ message += " ] to continue.";
+ log.debug(message);
+
+ // For each allow event, synchronize on the threads lock then set the event flag to true.
+ for (int id : threads)
+ {
+ // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
+ // being blocked at this time.
+ caller.setWaitingOnCoordinator(true);
+
+ synchronized (locks[id])
+ {
+ // Release the wating on coordinator flag now that this thread is running again.
+ caller.setWaitingOnCoordinator(false);
+
+ // Send the allow to continue event to the receiving thread.
+ allowEvents[id][callerId] = true;
+ }
+ }
+
+ // Wake up any threads waiting on the coordinator lock to recheck their event queues.
+ // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
+ // being blocked at this time.
+ caller.setWaitingOnCoordinator(true);
+
+ synchronized (coordinatorLock)
+ {
+ // Release the wating on coordinator flag now that this thread is running again.
+ caller.setWaitingOnCoordinator(false);
+ coordinatorLock.notifyAll();
+ }
+ }
+
+ /**
+ * Consumes an 'allow to continue' from one of the specified threads or waits until one is available or in some
+ * cases if one of the specified threads is blocked elsewhere to accept that as an 'allow to continue' event.
+ *
+ * @param threads The set of threads to accept an allow to continue event from.
+ * @param otherWaitIsAllow Whether or not to accept threads being blocked elsewhere as permission to continue.
+ * @param callerId The explicit id of the calling test thread.
+ * @param caller The calling test thread.
+ *
+ * @return If the <tt>otherWaitIsAllow</tt> flag is set, then <tt>true</tt> is returned when the thread being waited on is found
+ * to be blocked outside of the thread test coordinator. <tt>false</tt> under all other conditions.
+ */
+ boolean consumeAllowEvent(int[] threads, boolean otherWaitIsAllow, int callerId, TestRunnable caller)
+ {
+ // Generate some debugging messages. Very usefull to know how thread synchronization is progressing.
+ String message = "Thread " + callerId + " is requesting threads [ ";
+
+ // Record the time at which this method was called. Will be used for breaking out of potential deadlocks.
+ long startTime = System.nanoTime();
+
+ for (int j = 0; j < threads.length; j++)
+ {
+ message += threads[j] + ((j < (threads.length - 1)) ? ", " : "");
+ }
+
+ message += " ] to allow it to continue.";
+ log.debug(message);
+
+ // Loop until an allow to continue event is received.
+ while (true)
+ {
+ // Look at all the allowing thread to see if one has created an event for consumption.
+ for (int allowerId : threads)
+ {
+ // Get the threads lock for the event to consume.
+ // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
+ // being blocked at this time.
+ caller.setWaitingOnCoordinator(true);
+
+ synchronized (locks[callerId])
+ {
+ // Release the wating on coordinator flag now that this thread is running again.
+ caller.setWaitingOnCoordinator(false);
+
+ // Check if there is an event on the queue from the allowing thread to this one.
+ if (allowEvents[callerId][allowerId])
+ {
+ log.debug("Found an allow event, thread " + allowerId + ", is allowing thread " + callerId
+ + ", to continue.");
+
+ // Consume all the allow events for this thread.
+ /*for (int i = 0; i < allowEvents[callerId].length; i++)
+ {
+ allowEvents[callerId][i] = false;
+ }*/
+
+ // Consume just the event from the allower to the consumer, leaving other pending allow events alone.
+ allowEvents[callerId][allowerId] = false;
+
+ return false;
+ }
+ }
+ }
+
+ // If waiting elsewhere is to be interpreted as an 'allow to continue' event, then look at the thread status
+ // for the threads being waited on to see if any are blocked on other resources.
+ if (otherWaitIsAllow)
+ {
+ log.debug("Other wait is to be interpreted as an allow event.");
+
+ // Look at all the potential allower threads.
+ for (int allowerId : threads)
+ {
+ // Get the Java thread state for the allowing thread.
+ Thread threadToTest = testThreads[allowerId].getThread();
+ Thread.State state = threadToTest.getState();
+
+ // Check if the thread is blocked and so a potential candidate for releasing this one.
+ if ((state == Thread.State.BLOCKED) || (state == Thread.State.WAITING)
+ || (state == Thread.State.TIMED_WAITING))
+ {
+ log.debug("Found an allower thread, id = " + allowerId + ", that is blocked or wating.");
+
+ // Check that the allower thread is not waiting on the coordinator lock or any of the
+ // individual thread locks. It must be waiting or blocked on another monitor.
+ TestRunnable allowingRunnable = testThreads[allowerId];
+ boolean isWaitingOnCoordinator = allowingRunnable.isWaitingOnCoordinator();
+
+ if (!isWaitingOnCoordinator)
+ {
+ log.debug("The allower thread, id = " + allowerId
+ + ", is blocked or waiting other than on the coordinator.");
+
+ // Get the threads lock for the event to consume.
+ caller.setWaitingOnCoordinator(true);
+
+ synchronized (locks[callerId])
+ {
+ caller.setWaitingOnCoordinator(false);
+
+ // Consume all the allow events for this thread.
+ for (int i = 0; i < allowEvents[callerId].length; i++)
+ {
+ allowEvents[callerId][i] = false;
+ }
+
+ return true;
+ }
+ }
+ else
+ {
+ log.debug("The waiting allower thread, " + allowerId
+ + ", is waiting on the coordinator so does not allow thread " + callerId + " to continue.");
+ }
+ }
+ }
+ }
+
+ // Keep waiting until an 'allow to continue' event can be consumed.
+ try
+ {
+ // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
+ // being blocked at this time.
+ caller.setWaitingOnCoordinator(true);
+
+ synchronized (coordinatorLock)
+ {
+ // Release the wating on coordinator flag now that this thread is running again.
+ caller.setWaitingOnCoordinator(false);
+
+ log.debug("Thread " + callerId + " is waiting on coordinator lock for more allow events.");
+
+ // Set the waiting on coordinator flag to true in case the coordinator tries to test this thread for
+ // being blocked at this time.
+ caller.setWaitingOnCoordinator(true);
+ coordinatorLock.wait(10);
+ }
+ }
+ catch (InterruptedException e)
+ { }
+
+ // Release the waiting on coordinator flag now that this thread is running again.
+ caller.setWaitingOnCoordinator(false);
+
+ // Check if this thread has been waiting for longer than the deadlock timeout and raise a possible
+ // deadlock exception if so.
+ long waitTime = System.nanoTime() - startTime;
+ log.debug("Thread " + callerId + " has been waiting for " + (waitTime / 1000000) + " milliseconds.");
+
+ if (waitTime > deadlockTimeout)
+ {
+ // Throw a possible deadlock exception.
+ throw new PossibleDeadlockException("Possible deadlock due to timeout with state:\n" + this);
+ }
+
+ log.debug("Thread " + callerId + " has woken up, was waiting for more allow events to become available.");
+ }
+ }
+
+ /**
+ * Pretty prints the state of the thread test coordinator, for debugging purposes.
+ *
+ * @return Pretty printed state of the thread test coordinator.
+ */
+ public String toString()
+ {
+ String result = "[";
+
+ for (int i = 0; i < allowEvents.length; i++)
+ {
+ for (int j = 0; j < allowEvents[i].length; j++)
+ {
+ result += allowEvents[i][j];
+
+ result += (j < (allowEvents[i].length - 1)) ? ", " : "";
+ }
+
+ result += (i < (allowEvents.length - 1)) ? ",\n " : "";
+ }
+
+ result += "]";
+
+ for (int i = 0; i < testThreads.length; i++)
+ {
+ result += "thread[" + i + "] = " + testThreads[i].toString();
+ }
+
+ return result;
+ }
+
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java
index ef177a4255..b9865f2e22 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/concurrency/ThreadTestExample.java
@@ -1,145 +1,145 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.concurrency;
-
-import org.apache.log4j.Logger;
-
-/**
- * An example to illustrate the use of the {@link ThreadTestCoordinator} and {@link TestRunnable}s.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Demo multi-threaded testing.
- * </table>
- *
- * @author Rupert Smith
- */
-public class ThreadTestExample
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(ThreadTestExample.class);
-
- /** Test thread 1. */
- TestRunnable testThread1 =
- new TestRunnable()
- {
- public void runWithExceptions() throws Exception
- {
- log.debug("public void run(): called");
- log.info("in testThread0, block 1");
-
- // Wait for t2 to allow t1 to continue.
- allow(new int[] { 1 });
- waitFor(new int[] { 1 }, false);
-
- log.info("in testThread0, block 2");
-
- // Wait for t2 to allow t1 to continue. T2 is allowed to be blocked elsewhere than giving explicit
- // permission to allow t1 to continue.
- allow(new int[] { 1 });
- waitFor(new int[] { 1 }, true);
-
- log.info("in testThread0, block 3");
-
- // Release thread 2 from waiting on the shared lock.
- synchronized (sharedLock)
- {
- sharedLock.notifyAll();
- }
-
- allow(new int[] { 1 });
- }
- };
-
- /** A shared lock between the test threads. */
- final Object sharedLock = new Object();
-
- /** Test thread 2. */
- TestRunnable testThread2 =
- new TestRunnable()
- {
- public void runWithExceptions() throws Exception
- {
- log.debug("public void run(): called");
- log.info("in testThread1, block 1");
-
- // Wait for t1 to allow t2 to continue.
- allow(new int[] { 0 });
- waitFor(new int[] { 0 }, false);
-
- log.info("in testThread1, block 2");
-
- // Wait on another resource. T1 should accept this as permission to continue.
- try
- {
- synchronized (sharedLock)
- {
- log.debug("in testThread1, waiting on shared lock.");
- sharedLock.wait();
- }
- }
- catch (InterruptedException e)
- {
- // Bail-out with a runtime if this happens.
- throw new RuntimeException("Interrupted whilst waiting for shared lock.", e);
- }
-
- log.info("in testThread1, finished waiting on shared lock.");
-
- // allow(new int[] { 0 });
-
- // Wait for t1 to allow t2 to continue.
- waitFor(new int[] { 0 }, false);
-
- log.info("in testThread1, block 3");
-
- allow(new int[] { 0 });
- }
- };
-
- /**
- * Executes the test threads with coordination.
- *
- * @param args Ignored.
- */
- public void main(String[] args)
- {
- ThreadTestCoordinator tt = new ThreadTestCoordinator(2);
-
- tt.addTestThread(testThread1, 0);
- tt.addTestThread(testThread2, 1);
- tt.setDeadlockTimeout(500);
- tt.run();
-
- String errorMessage = tt.joinAndRetrieveMessages();
-
- // Print any error messages or exceptions.
- log.info(errorMessage);
-
- if (!tt.getExceptions().isEmpty())
- {
- for (Exception e : tt.getExceptions())
- {
- log.warn("Exception thrown during test thread: ", e);
- }
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.concurrency;
+
+import org.apache.log4j.Logger;
+
+/**
+ * An example to illustrate the use of the {@link ThreadTestCoordinator} and {@link TestRunnable}s.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Demo multi-threaded testing.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ThreadTestExample
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(ThreadTestExample.class);
+
+ /** Test thread 1. */
+ TestRunnable testThread1 =
+ new TestRunnable()
+ {
+ public void runWithExceptions() throws Exception
+ {
+ log.debug("public void run(): called");
+ log.info("in testThread0, block 1");
+
+ // Wait for t2 to allow t1 to continue.
+ allow(new int[] { 1 });
+ waitFor(new int[] { 1 }, false);
+
+ log.info("in testThread0, block 2");
+
+ // Wait for t2 to allow t1 to continue. T2 is allowed to be blocked elsewhere than giving explicit
+ // permission to allow t1 to continue.
+ allow(new int[] { 1 });
+ waitFor(new int[] { 1 }, true);
+
+ log.info("in testThread0, block 3");
+
+ // Release thread 2 from waiting on the shared lock.
+ synchronized (sharedLock)
+ {
+ sharedLock.notifyAll();
+ }
+
+ allow(new int[] { 1 });
+ }
+ };
+
+ /** A shared lock between the test threads. */
+ final Object sharedLock = new Object();
+
+ /** Test thread 2. */
+ TestRunnable testThread2 =
+ new TestRunnable()
+ {
+ public void runWithExceptions() throws Exception
+ {
+ log.debug("public void run(): called");
+ log.info("in testThread1, block 1");
+
+ // Wait for t1 to allow t2 to continue.
+ allow(new int[] { 0 });
+ waitFor(new int[] { 0 }, false);
+
+ log.info("in testThread1, block 2");
+
+ // Wait on another resource. T1 should accept this as permission to continue.
+ try
+ {
+ synchronized (sharedLock)
+ {
+ log.debug("in testThread1, waiting on shared lock.");
+ sharedLock.wait();
+ }
+ }
+ catch (InterruptedException e)
+ {
+ // Bail-out with a runtime if this happens.
+ throw new RuntimeException("Interrupted whilst waiting for shared lock.", e);
+ }
+
+ log.info("in testThread1, finished waiting on shared lock.");
+
+ // allow(new int[] { 0 });
+
+ // Wait for t1 to allow t2 to continue.
+ waitFor(new int[] { 0 }, false);
+
+ log.info("in testThread1, block 3");
+
+ allow(new int[] { 0 });
+ }
+ };
+
+ /**
+ * Executes the test threads with coordination.
+ *
+ * @param args Ignored.
+ */
+ public void main(String[] args)
+ {
+ ThreadTestCoordinator tt = new ThreadTestCoordinator(2);
+
+ tt.addTestThread(testThread1, 0);
+ tt.addTestThread(testThread2, 1);
+ tt.setDeadlockTimeout(500);
+ tt.run();
+
+ String errorMessage = tt.joinAndRetrieveMessages();
+
+ // Print any error messages or exceptions.
+ log.info(errorMessage);
+
+ if (!tt.getExceptions().isEmpty())
+ {
+ for (Exception e : tt.getExceptions())
+ {
+ log.warn("Exception thrown during test thread: ", e);
+ }
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java
index 03e465695e..58a7f60f3c 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestCase.java
@@ -1,303 +1,303 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.TestCase;
-
-import org.apache.log4j.Logger;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/**
- * AsymptoticTestCase is an extension of TestCase for writing unit tests to analyze asymptotic time and space behaviour.
- *
- * <p>ParameterizedTestCases allow tests to be defined which have test methods that take a single int argument. Normal
- * JUnit test methods do not take any arguments. This int argument can be interpreted in any way by the test but it is
- * intended to denote the 'size' of the test to be run. For example, when testing the performance of a data structure
- * for different numbers of data elements held in the data structure the int parameter should be interpreted as the
- * number of elements. Test timings for different numbers of elements can then be captured and the asymptotic behaviour
- * of the data structure with respect to time analyzed. Any non-parameterized tests defined in extensions of this class
- * will also be run.
- *
- * <p>TestCases derived from this class may also define tear down methods to clean up their memory usage. This is
- * intended to be used in conjunction with memory listeners that report the amount of memory a test uses. The idea is
- * to write a test that allocates memory in the main test method in such a way that it leaves that memory still
- * allocated at the end of the test. The amount of memory used can then be measured before calling the tear down method
- * to clean it up. In the data structure example above, a test will allocate as many elements as are requested by the
- * int parameter and deallocate them in the tear down method. In this way memory readings for different numbers of
- * elements can be captured and the asymptotic behaviour of the data structure with respect to space analyzed.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Store the current int parameter value. <td> {@link TKTestResult} and see {@link AsymptoticTestDecorator} too.
- * <tr><td> Invoke parameterized test methods.
- * </table>
- *
- * @todo If possible try to move the code that invokes the test and setup/teardown methods into {@link TKTestResult} or
- * {@link AsymptoticTestDecorator} rather than this class. This would mean that tests don't have to extend this
- * class to do time and space performance analysis, these methods could be added to any JUnit TestCase class
- * instead. This would be an improvement because existing unit tests wouldn't have to extend a different class to
- * work with this extension, and also tests that extend other junit extension classes could have parameterized
- * and tear down methods too.
- *
- * @author Rupert Smith
- */
-public class AsymptoticTestCase extends TestCase implements InstrumentedTest
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(AsymptoticTestCase.class);
-
- /** The name of the test case. */
- private String testCaseName;
-
- /** Thread local for holding measurements on a per thread basis. */
- ThreadLocal<TestMeasurements> threadLocalMeasurement =
- new ThreadLocal<TestMeasurements>()
- {
- /**
- * Sets up a default set test measurements (zeroed, apart from the size param which defaults to 1).
- *
- * @return A set of default test measurements.
- */
- protected synchronized TestMeasurements initialValue()
- {
- return new TestMeasurements();
- }
- };
-
- /**
- * Constructs a test case with the given name.
- *
- * @param name The name of the test.
- */
- public AsymptoticTestCase(String name)
- {
- super(name);
-
- log.debug("public AsymptoticTestCase(String " + name + "): called");
- testCaseName = name;
- }
-
- /**
- * Gets the current value of the integer parameter to be passed to the parameterized test.
- *
- * @return The current value of the integer parameter.
- */
- public int getN()
- {
- log.debug("public int getN(): called");
- int n = threadLocalMeasurement.get().n;
-
- log.debug("return: " + n);
-
- return n;
- }
-
- /**
- * Sets the current value of the integer parameter to be passed to the parameterized test.
- *
- * @param n The new current value of the integer parameter.
- */
- public void setN(int n)
- {
- log.debug("public void setN(int " + n + "): called");
- threadLocalMeasurement.get().n = n;
- }
-
- /**
- * Reports how long the test took to run.
- *
- * @return The time in milliseconds that the test took to run.
- */
- public long getTestTime()
- {
- log.debug("public long getTestTime(): called");
- long startTime = threadLocalMeasurement.get().startTime;
- long endTime = threadLocalMeasurement.get().endTime;
- long testTime = endTime - startTime;
-
- log.debug("return: " + testTime);
-
- return testTime;
- }
-
- /**
- * Reports the memory usage at the start of the test.
- *
- * @return The memory usage at the start of the test.
- */
- public long getTestStartMemory()
- {
- // log.debug("public long getTestStartMemory(): called");
- long startMem = threadLocalMeasurement.get().startMem;
-
- // log.debug("return: " + startMem);
-
- return startMem;
- }
-
- /**
- * Reports the memory usage at the end of the test.
- *
- * @return The memory usage at the end of the test.
- */
- public long getTestEndMemory()
- {
- // log.debug("public long getTestEndMemory(): called");
- long endMem = threadLocalMeasurement.get().endMem;
-
- // log.debug("return: " + endMem);
- return endMem;
- }
-
- /**
- * Resets the instrumentation values to zero, and nulls any references to held measurements so that the memory
- * can be reclaimed.
- */
- public void reset()
- {
- log.debug("public void reset(): called");
- threadLocalMeasurement.remove();
- }
-
- /**
- * Runs the test method for this test case.
- *
- * @throws Throwable Any Throwables from the test methods invoked are allowed to fall through.
- */
- protected void runTest() throws Throwable
- {
- log.debug("protected void runTest(): called");
-
- // Check that a test name has been set. This is used to define which method to run.
- assertNotNull(testCaseName);
- log.debug("testCaseName = " + testCaseName);
-
- // Try to get the method with matching name.
- Method runMethod = null;
- boolean isParameterized = false;
-
- // Check if a parameterized test method is available.
- try
- {
- // Use getMethod to get all public inherited methods. getDeclaredMethods returns all
- // methods of this class but excludes the inherited ones.
- runMethod = getClass().getMethod(testCaseName, int.class);
- isParameterized = true;
- }
- catch (NoSuchMethodException e)
- {
- // log.debug("Parameterized method \"" + testCaseName + "\" not found.");
- // Set run method to null (it already will be but...) to indicate that no parameterized method
- // version could be found.
- runMethod = null;
- }
-
- // If no parameterized method is available, try and get the unparameterized method.
- if (runMethod == null)
- {
- try
- {
- runMethod = getClass().getMethod(testCaseName);
- isParameterized = false;
-
- }
- catch (NoSuchMethodException e)
- {
- fail("Method \"" + testCaseName + "\" not found.");
- }
- }
-
- // Check that the method is publicly accessable.
- if (!Modifier.isPublic(runMethod.getModifiers()))
- {
- fail("Method \"" + testCaseName + "\" should be public.");
- }
-
- // Try to execute the method, passing it the current int parameter value. Allow any invocation exceptions or
- // resulting exceptions from the method to fall through.
- try
- {
- Integer paramN = getN();
- log.debug("paramN = " + paramN);
-
- // Calculate parameters for parameterized tests so new does not get called during memory measurement.
- Object[] params = new Object[] { paramN };
-
- // Take the test start memory and start time.
- threadLocalMeasurement.get().startMem = 0; // SizeOf.getUsedMemory();
-
- threadLocalMeasurement.get().startTime = System.nanoTime();
-
- if (isParameterized)
- {
- runMethod.invoke(this, params);
- }
- else
- {
- runMethod.invoke(this);
- }
- }
- catch (InvocationTargetException e)
- {
- e.fillInStackTrace();
- throw e.getTargetException();
- }
- catch (IllegalAccessException e)
- {
- e.fillInStackTrace();
- throw e;
- }
- finally
- {
- // Take the test end memory and end time and calculate how long it took to run.
- long endTime = System.nanoTime();
- threadLocalMeasurement.get().endTime = endTime;
- log.debug("startTime = " + threadLocalMeasurement.get().startTime + ", endTime = " + endTime + ", testTime = "
- + getTestTime());
-
- threadLocalMeasurement.get().endMem = 0; // SizeOf.getUsedMemory();
- }
- }
-
- /**
- * The test parameters, encapsulated as a unit for attaching on a per thread basis.
- */
- private static class TestMeasurements
- {
- /** Holds the current value of the integer parameter to run tests on. */
- public int n = 1;
-
- /** Holds the test start memory. */
- public long startTime = 0;
-
- /** Holds the test end memory. */
- public long endTime = 0;
-
- /** Holds the test start memory. */
- public long startMem = 0;
-
- /** Holds the test end memory. */
- public long endMem = 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.junit.extensions;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * AsymptoticTestCase is an extension of TestCase for writing unit tests to analyze asymptotic time and space behaviour.
+ *
+ * <p>ParameterizedTestCases allow tests to be defined which have test methods that take a single int argument. Normal
+ * JUnit test methods do not take any arguments. This int argument can be interpreted in any way by the test but it is
+ * intended to denote the 'size' of the test to be run. For example, when testing the performance of a data structure
+ * for different numbers of data elements held in the data structure the int parameter should be interpreted as the
+ * number of elements. Test timings for different numbers of elements can then be captured and the asymptotic behaviour
+ * of the data structure with respect to time analyzed. Any non-parameterized tests defined in extensions of this class
+ * will also be run.
+ *
+ * <p>TestCases derived from this class may also define tear down methods to clean up their memory usage. This is
+ * intended to be used in conjunction with memory listeners that report the amount of memory a test uses. The idea is
+ * to write a test that allocates memory in the main test method in such a way that it leaves that memory still
+ * allocated at the end of the test. The amount of memory used can then be measured before calling the tear down method
+ * to clean it up. In the data structure example above, a test will allocate as many elements as are requested by the
+ * int parameter and deallocate them in the tear down method. In this way memory readings for different numbers of
+ * elements can be captured and the asymptotic behaviour of the data structure with respect to space analyzed.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Store the current int parameter value. <td> {@link TKTestResult} and see {@link AsymptoticTestDecorator} too.
+ * <tr><td> Invoke parameterized test methods.
+ * </table>
+ *
+ * @todo If possible try to move the code that invokes the test and setup/teardown methods into {@link TKTestResult} or
+ * {@link AsymptoticTestDecorator} rather than this class. This would mean that tests don't have to extend this
+ * class to do time and space performance analysis, these methods could be added to any JUnit TestCase class
+ * instead. This would be an improvement because existing unit tests wouldn't have to extend a different class to
+ * work with this extension, and also tests that extend other junit extension classes could have parameterized
+ * and tear down methods too.
+ *
+ * @author Rupert Smith
+ */
+public class AsymptoticTestCase extends TestCase implements InstrumentedTest
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(AsymptoticTestCase.class);
+
+ /** The name of the test case. */
+ private String testCaseName;
+
+ /** Thread local for holding measurements on a per thread basis. */
+ ThreadLocal<TestMeasurements> threadLocalMeasurement =
+ new ThreadLocal<TestMeasurements>()
+ {
+ /**
+ * Sets up a default set test measurements (zeroed, apart from the size param which defaults to 1).
+ *
+ * @return A set of default test measurements.
+ */
+ protected synchronized TestMeasurements initialValue()
+ {
+ return new TestMeasurements();
+ }
+ };
+
+ /**
+ * Constructs a test case with the given name.
+ *
+ * @param name The name of the test.
+ */
+ public AsymptoticTestCase(String name)
+ {
+ super(name);
+
+ log.debug("public AsymptoticTestCase(String " + name + "): called");
+ testCaseName = name;
+ }
+
+ /**
+ * Gets the current value of the integer parameter to be passed to the parameterized test.
+ *
+ * @return The current value of the integer parameter.
+ */
+ public int getN()
+ {
+ log.debug("public int getN(): called");
+ int n = threadLocalMeasurement.get().n;
+
+ log.debug("return: " + n);
+
+ return n;
+ }
+
+ /**
+ * Sets the current value of the integer parameter to be passed to the parameterized test.
+ *
+ * @param n The new current value of the integer parameter.
+ */
+ public void setN(int n)
+ {
+ log.debug("public void setN(int " + n + "): called");
+ threadLocalMeasurement.get().n = n;
+ }
+
+ /**
+ * Reports how long the test took to run.
+ *
+ * @return The time in milliseconds that the test took to run.
+ */
+ public long getTestTime()
+ {
+ log.debug("public long getTestTime(): called");
+ long startTime = threadLocalMeasurement.get().startTime;
+ long endTime = threadLocalMeasurement.get().endTime;
+ long testTime = endTime - startTime;
+
+ log.debug("return: " + testTime);
+
+ return testTime;
+ }
+
+ /**
+ * Reports the memory usage at the start of the test.
+ *
+ * @return The memory usage at the start of the test.
+ */
+ public long getTestStartMemory()
+ {
+ // log.debug("public long getTestStartMemory(): called");
+ long startMem = threadLocalMeasurement.get().startMem;
+
+ // log.debug("return: " + startMem);
+
+ return startMem;
+ }
+
+ /**
+ * Reports the memory usage at the end of the test.
+ *
+ * @return The memory usage at the end of the test.
+ */
+ public long getTestEndMemory()
+ {
+ // log.debug("public long getTestEndMemory(): called");
+ long endMem = threadLocalMeasurement.get().endMem;
+
+ // log.debug("return: " + endMem);
+ return endMem;
+ }
+
+ /**
+ * Resets the instrumentation values to zero, and nulls any references to held measurements so that the memory
+ * can be reclaimed.
+ */
+ public void reset()
+ {
+ log.debug("public void reset(): called");
+ threadLocalMeasurement.remove();
+ }
+
+ /**
+ * Runs the test method for this test case.
+ *
+ * @throws Throwable Any Throwables from the test methods invoked are allowed to fall through.
+ */
+ protected void runTest() throws Throwable
+ {
+ log.debug("protected void runTest(): called");
+
+ // Check that a test name has been set. This is used to define which method to run.
+ assertNotNull(testCaseName);
+ log.debug("testCaseName = " + testCaseName);
+
+ // Try to get the method with matching name.
+ Method runMethod = null;
+ boolean isParameterized = false;
+
+ // Check if a parameterized test method is available.
+ try
+ {
+ // Use getMethod to get all public inherited methods. getDeclaredMethods returns all
+ // methods of this class but excludes the inherited ones.
+ runMethod = getClass().getMethod(testCaseName, int.class);
+ isParameterized = true;
+ }
+ catch (NoSuchMethodException e)
+ {
+ // log.debug("Parameterized method \"" + testCaseName + "\" not found.");
+ // Set run method to null (it already will be but...) to indicate that no parameterized method
+ // version could be found.
+ runMethod = null;
+ }
+
+ // If no parameterized method is available, try and get the unparameterized method.
+ if (runMethod == null)
+ {
+ try
+ {
+ runMethod = getClass().getMethod(testCaseName);
+ isParameterized = false;
+
+ }
+ catch (NoSuchMethodException e)
+ {
+ fail("Method \"" + testCaseName + "\" not found.");
+ }
+ }
+
+ // Check that the method is publicly accessable.
+ if (!Modifier.isPublic(runMethod.getModifiers()))
+ {
+ fail("Method \"" + testCaseName + "\" should be public.");
+ }
+
+ // Try to execute the method, passing it the current int parameter value. Allow any invocation exceptions or
+ // resulting exceptions from the method to fall through.
+ try
+ {
+ Integer paramN = getN();
+ log.debug("paramN = " + paramN);
+
+ // Calculate parameters for parameterized tests so new does not get called during memory measurement.
+ Object[] params = new Object[] { paramN };
+
+ // Take the test start memory and start time.
+ threadLocalMeasurement.get().startMem = 0; // SizeOf.getUsedMemory();
+
+ threadLocalMeasurement.get().startTime = System.nanoTime();
+
+ if (isParameterized)
+ {
+ runMethod.invoke(this, params);
+ }
+ else
+ {
+ runMethod.invoke(this);
+ }
+ }
+ catch (InvocationTargetException e)
+ {
+ e.fillInStackTrace();
+ throw e.getTargetException();
+ }
+ catch (IllegalAccessException e)
+ {
+ e.fillInStackTrace();
+ throw e;
+ }
+ finally
+ {
+ // Take the test end memory and end time and calculate how long it took to run.
+ long endTime = System.nanoTime();
+ threadLocalMeasurement.get().endTime = endTime;
+ log.debug("startTime = " + threadLocalMeasurement.get().startTime + ", endTime = " + endTime + ", testTime = "
+ + getTestTime());
+
+ threadLocalMeasurement.get().endMem = 0; // SizeOf.getUsedMemory();
+ }
+ }
+
+ /**
+ * The test parameters, encapsulated as a unit for attaching on a per thread basis.
+ */
+ private static class TestMeasurements
+ {
+ /** Holds the current value of the integer parameter to run tests on. */
+ public int n = 1;
+
+ /** Holds the test start memory. */
+ public long startTime = 0;
+
+ /** Holds the test end memory. */
+ public long endTime = 0;
+
+ /** Holds the test start memory. */
+ public long startMem = 0;
+
+ /** Holds the test end memory. */
+ public long endMem = 0;
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java
index e99f904331..4faa58688f 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/AsymptoticTestDecorator.java
@@ -1,170 +1,170 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.TestResult;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.util.MathUtils;
-
-/**
- * A Decorator that runs a test repeatedly on an increasing int parameter, or for a fixed number of repeats. If both
- * a set of integer parameters and a repeat count are specified, then each test is run for the repeat count at each
- * integer parameter.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Repeat a test for each of a set of integer parameters. <td> {@link TKTestResult}
- * <tr><td> Repeat a test multiple times.
- * <tr><td>
- * </table>
- *
- * @author Rupert Smith
- */
-public class AsymptoticTestDecorator extends WrappedSuiteTestDecorator
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(AsymptoticTestDecorator.class);
-
- /** The int size parameters to run the test with. */
- private int[] params;
-
- /** The number of times the whole test should be repeated. */
- private int repeat;
-
- /**
- * Creates an asymptotic test decorator that wraps a test with repeats and a set of integer 'size' paramters
- * to call the test with.
- *
- * @param test The test to wrap.
- * @param params The integer 'size' parameters.
- * @param repeat The number of times to repeat the test.
- */
- public AsymptoticTestDecorator(WrappedSuiteTestDecorator test, int[] params, int repeat)
- {
- super(test);
-
- log.debug("public AsymptoticTestDecorator(Test \"" + test + "\", int[] "
- + ((params == null) ? null : MathUtils.printArray(params)) + ", int " + repeat + "): called");
-
- this.params = params;
- this.repeat = repeat;
- }
-
- /**
- * Creates a new AsymptoticTestDecorator object.
- *
- * @param test The test to decorate.
- * @param start The starting asymptotic integer parameter value.
- * @param end The ending asymptotic integer parameter value.
- * @param step The increment size to move from the start to end values by.
- * @param repeat The number of times to repeat the test at each step of the cycle.
- */
- public AsymptoticTestDecorator(WrappedSuiteTestDecorator test, int start, int end, int step, int repeat)
- {
- super(test);
-
- if (start < 0)
- {
- throw new IllegalArgumentException("Start must be >= 0");
- }
-
- if (end < start)
- {
- throw new IllegalArgumentException("End must be >= start");
- }
-
- if (step < 1)
- {
- throw new IllegalArgumentException("Step must be >= 1");
- }
-
- if (repeat < 1)
- {
- throw new IllegalArgumentException("Repeat must be >= 1");
- }
-
- // Generate the sequence.
- params = new int[((end - start) / step) + 1];
- int i = 0;
- for (int n = start; n <= end; n += step)
- {
- params[i++] = n;
- }
-
- this.repeat = repeat;
- }
-
- /**
- * Runs the test repeatedly for each value of the int parameter specified and for the correct number of test
- * repeats.
- *
- * @param result The test result object that the tests will indicate their results to. This is also used
- * to pass the int parameter from this class to the decorated test class.
- */
- public void run(TestResult result)
- {
- log.debug("public void run(TestResult result): called");
-
- if (!(result instanceof TKTestResult))
- {
- throw new IllegalArgumentException("AsymptoticTestDecorator only works with TKTestResult");
- }
-
- // Cast the test result into a TKTestResult to place the current parameter into.
- TKTestResult tkResult = (TKTestResult) result;
-
- log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
- log.debug("repeat = " + repeat);
-
- for (int n : params)
- {
- for (int j = 0; j < repeat; j++)
- {
- log.debug("n = " + n);
-
- // Set the integer parameter in the TKTestResult to be passed to the tests.
- tkResult.setN(n);
-
- if (tkResult.shouldStop())
- {
- log.debug("tkResult.shouldStop = " + true);
-
- break;
- }
-
- log.debug("Calling super#run");
- super.run(tkResult);
- }
- }
- }
-
- /**
- * Prints out the name of this test with the string "(parameterized)" appended onto it for debugging purposes.
- *
- * @return The name of this test with the string "(parameterized)" appended onto it.
- */
- public String toString()
- {
- return super.toString() + "(parameterized)";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.TestResult;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.util.MathUtils;
+
+/**
+ * A Decorator that runs a test repeatedly on an increasing int parameter, or for a fixed number of repeats. If both
+ * a set of integer parameters and a repeat count are specified, then each test is run for the repeat count at each
+ * integer parameter.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Repeat a test for each of a set of integer parameters. <td> {@link TKTestResult}
+ * <tr><td> Repeat a test multiple times.
+ * <tr><td>
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class AsymptoticTestDecorator extends WrappedSuiteTestDecorator
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(AsymptoticTestDecorator.class);
+
+ /** The int size parameters to run the test with. */
+ private int[] params;
+
+ /** The number of times the whole test should be repeated. */
+ private int repeat;
+
+ /**
+ * Creates an asymptotic test decorator that wraps a test with repeats and a set of integer 'size' paramters
+ * to call the test with.
+ *
+ * @param test The test to wrap.
+ * @param params The integer 'size' parameters.
+ * @param repeat The number of times to repeat the test.
+ */
+ public AsymptoticTestDecorator(WrappedSuiteTestDecorator test, int[] params, int repeat)
+ {
+ super(test);
+
+ log.debug("public AsymptoticTestDecorator(Test \"" + test + "\", int[] "
+ + ((params == null) ? null : MathUtils.printArray(params)) + ", int " + repeat + "): called");
+
+ this.params = params;
+ this.repeat = repeat;
+ }
+
+ /**
+ * Creates a new AsymptoticTestDecorator object.
+ *
+ * @param test The test to decorate.
+ * @param start The starting asymptotic integer parameter value.
+ * @param end The ending asymptotic integer parameter value.
+ * @param step The increment size to move from the start to end values by.
+ * @param repeat The number of times to repeat the test at each step of the cycle.
+ */
+ public AsymptoticTestDecorator(WrappedSuiteTestDecorator test, int start, int end, int step, int repeat)
+ {
+ super(test);
+
+ if (start < 0)
+ {
+ throw new IllegalArgumentException("Start must be >= 0");
+ }
+
+ if (end < start)
+ {
+ throw new IllegalArgumentException("End must be >= start");
+ }
+
+ if (step < 1)
+ {
+ throw new IllegalArgumentException("Step must be >= 1");
+ }
+
+ if (repeat < 1)
+ {
+ throw new IllegalArgumentException("Repeat must be >= 1");
+ }
+
+ // Generate the sequence.
+ params = new int[((end - start) / step) + 1];
+ int i = 0;
+ for (int n = start; n <= end; n += step)
+ {
+ params[i++] = n;
+ }
+
+ this.repeat = repeat;
+ }
+
+ /**
+ * Runs the test repeatedly for each value of the int parameter specified and for the correct number of test
+ * repeats.
+ *
+ * @param result The test result object that the tests will indicate their results to. This is also used
+ * to pass the int parameter from this class to the decorated test class.
+ */
+ public void run(TestResult result)
+ {
+ log.debug("public void run(TestResult result): called");
+
+ if (!(result instanceof TKTestResult))
+ {
+ throw new IllegalArgumentException("AsymptoticTestDecorator only works with TKTestResult");
+ }
+
+ // Cast the test result into a TKTestResult to place the current parameter into.
+ TKTestResult tkResult = (TKTestResult) result;
+
+ log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
+ log.debug("repeat = " + repeat);
+
+ for (int n : params)
+ {
+ for (int j = 0; j < repeat; j++)
+ {
+ log.debug("n = " + n);
+
+ // Set the integer parameter in the TKTestResult to be passed to the tests.
+ tkResult.setN(n);
+
+ if (tkResult.shouldStop())
+ {
+ log.debug("tkResult.shouldStop = " + true);
+
+ break;
+ }
+
+ log.debug("Calling super#run");
+ super.run(tkResult);
+ }
+ }
+ }
+
+ /**
+ * Prints out the name of this test with the string "(parameterized)" appended onto it for debugging purposes.
+ *
+ * @return The name of this test with the string "(parameterized)" appended onto it.
+ */
+ public String toString()
+ {
+ return super.toString() + "(parameterized)";
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java
index e8e203f0a3..61d5746421 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BaseThrottle.java
@@ -1,98 +1,98 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-/**
- * Provides a base implementation of the non-waiting throttle checking method, using the system nano timer.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check against a throttle speed without waiting.
- * </table>
- *
- * @author Rupert Smith
- */
-public abstract class BaseThrottle implements Throttle
-{
- /** Holds the length of a single cycle in nano seconds. */
- protected long cycleTimeNanos;
-
- /** Holds the time of the last succesfull call to the check method. */
- private long lastCheckTimeNanos;
-
- /** Flag used to detect the first call to the {@link #checkThrottle()} method. */
- boolean firstCheckCall = true;
-
- /**
- * Flag used to detect the first call to the {@link #throttle()} method. Zero or negative start time cannot be
- * relied on to detect this as System.nanoTime can return zero or negative values.
- */
- boolean firstCall = true;
-
- /**
- * Specifies the throttling rate in operations per second. This must be called with with a value, the inverse
- * of which is a measurement in nano seconds, such that the number of nano seconds do not overflow a long integer.
- * The value must also be larger than zero.
- *
- * @param hertz The throttling rate in cycles per second.
- */
- public void setRate(float hertz)
- {
- // Check that the argument is above zero.
- if (hertz <= 0.0f)
- {
- throw new IllegalArgumentException("The throttle rate must be above zero.");
- }
-
- // Calculate the cycle time.
- cycleTimeNanos = (long) (1000000000f / hertz);
-
- // Reset the first pass flag.
- firstCall = false;
- firstCheckCall = false;
- }
-
- /**
- * Checks but does not enforce the throttle rate. When this method is called, it checks if a length of time greater
- * than that equal to the inverse of the throttling rate has passed since it was last called and returned <tt>true</tt>
- *
- * @return <tt>true</tt> if a length of time greater than that equal to the inverse of the throttling rate has
- * passed since this method was last called and returned <tt>true</tt>, <tt>false</tt> otherwise. The very
- * first time this method is called on a throttle, it returns <tt>true</tt> as the base case to the above
- * self-referential definition.
- */
- public boolean checkThrottle()
- {
- long now = System.nanoTime();
-
- if ((now > (cycleTimeNanos + lastCheckTimeNanos)) || firstCheckCall)
- {
- firstCheckCall = false;
- lastCheckTimeNanos = now;
-
- return true;
- }
- else
- {
- return false;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * Provides a base implementation of the non-waiting throttle checking method, using the system nano timer.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check against a throttle speed without waiting.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public abstract class BaseThrottle implements Throttle
+{
+ /** Holds the length of a single cycle in nano seconds. */
+ protected long cycleTimeNanos;
+
+ /** Holds the time of the last succesfull call to the check method. */
+ private long lastCheckTimeNanos;
+
+ /** Flag used to detect the first call to the {@link #checkThrottle()} method. */
+ boolean firstCheckCall = true;
+
+ /**
+ * Flag used to detect the first call to the {@link #throttle()} method. Zero or negative start time cannot be
+ * relied on to detect this as System.nanoTime can return zero or negative values.
+ */
+ boolean firstCall = true;
+
+ /**
+ * Specifies the throttling rate in operations per second. This must be called with with a value, the inverse
+ * of which is a measurement in nano seconds, such that the number of nano seconds do not overflow a long integer.
+ * The value must also be larger than zero.
+ *
+ * @param hertz The throttling rate in cycles per second.
+ */
+ public void setRate(float hertz)
+ {
+ // Check that the argument is above zero.
+ if (hertz <= 0.0f)
+ {
+ throw new IllegalArgumentException("The throttle rate must be above zero.");
+ }
+
+ // Calculate the cycle time.
+ cycleTimeNanos = (long) (1000000000f / hertz);
+
+ // Reset the first pass flag.
+ firstCall = false;
+ firstCheckCall = false;
+ }
+
+ /**
+ * Checks but does not enforce the throttle rate. When this method is called, it checks if a length of time greater
+ * than that equal to the inverse of the throttling rate has passed since it was last called and returned <tt>true</tt>
+ *
+ * @return <tt>true</tt> if a length of time greater than that equal to the inverse of the throttling rate has
+ * passed since this method was last called and returned <tt>true</tt>, <tt>false</tt> otherwise. The very
+ * first time this method is called on a throttle, it returns <tt>true</tt> as the base case to the above
+ * self-referential definition.
+ */
+ public boolean checkThrottle()
+ {
+ long now = System.nanoTime();
+
+ if ((now > (cycleTimeNanos + lastCheckTimeNanos)) || firstCheckCall)
+ {
+ firstCheckCall = false;
+ lastCheckTimeNanos = now;
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java
index 1d00fcf3b6..241e7aa2b7 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/BatchedThrottle.java
@@ -1,94 +1,94 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-/**
- * BatchedThrottle is a {@link SleepThrottle} that uses batching to achieve much higher throttling rates than a sleep
- * throttle can. Sleep throttle has difficulties once the rate gets above a few hundred hertz, because the JVM cannot
- * generate timed pauses that are that short. BatchedThrottle gets around this by only inserting pauses once every so
- * many calls to the {@link #throttle()} method, and using a sleep throttle run at a lower rate. The rate for the sleep
- * throttle is chosen so that it remains under 100hz. The final throttling rate of this throttle is equal to the batch
- * size times the rate of the underlying sleep throttle.
- *
- * <p/>The batching calculation involves taking the log to the base 100 of the desired rate and rounding this to
- * an integer. The batch size is always an exact power of 100 because of the rounding. The rate for an underlying
- * sleep throttle is then chosen appropriately.
- *
- * <p/>In practice, the accuracy of a BacthedThrottle skews off but can sometimes even be reasonable up to ten thousand
- * hertz compared with 100 Hz for a {@link SleepThrottle}.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept throttling rate in operations per second.
- * <tr><td> Inject short pauses, occasionaly, to fill out processing cycles to a specified rate.
- * <tr><td> Check against a throttle speed without waiting.
- * </table>
- *
- * @todo Should always round the log base 100 down to the nearest integer?
- *
- * @author Rupert Smith
- */
-public class BatchedThrottle extends BaseThrottle
-{
- /** Holds the batch size. */
- int batchSize;
-
- /** The call count within the current batch. */
- long callCount;
-
- /** Holds a sleep throttle configured to run at the batched rate. */
- private Throttle batchRateThrottle = new SleepThrottle();
-
- /**
- * Specifies the throttling rate in operations per second.
- *
- * @param hertz The throttling rate in cycles per second.
- */
- public void setRate(float hertz)
- {
- // Pass the rate unaltered down to the base implementation, for the check method.
- super.setRate(hertz);
-
- // Log base 10 over 2 is used here to get a feel for what power of 100 the total rate is.
- // As the total rate goes up the powers of 100 the batch size goes up by powers of 100 to keep the
- // throttle rate in the range 1 to 100.
- int x = (int) (Math.log10(hertz) / 2);
- batchSize = (int) Math.pow(100, x);
- float throttleRate = hertz / batchSize;
-
- // Reset the call count.
- callCount = 0;
-
- // Set the sleep throttle wrapped implementation at a rate within its abilities.
- batchRateThrottle.setRate(throttleRate);
- }
-
- /**
- * Throttle calls to this method to the rate specified by the {@link #setRate(float)} method.
- */
- public void throttle()
- {
- if ((callCount++ % batchSize) == 0)
- {
- batchRateThrottle.throttle();
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * BatchedThrottle is a {@link SleepThrottle} that uses batching to achieve much higher throttling rates than a sleep
+ * throttle can. Sleep throttle has difficulties once the rate gets above a few hundred hertz, because the JVM cannot
+ * generate timed pauses that are that short. BatchedThrottle gets around this by only inserting pauses once every so
+ * many calls to the {@link #throttle()} method, and using a sleep throttle run at a lower rate. The rate for the sleep
+ * throttle is chosen so that it remains under 100hz. The final throttling rate of this throttle is equal to the batch
+ * size times the rate of the underlying sleep throttle.
+ *
+ * <p/>The batching calculation involves taking the log to the base 100 of the desired rate and rounding this to
+ * an integer. The batch size is always an exact power of 100 because of the rounding. The rate for an underlying
+ * sleep throttle is then chosen appropriately.
+ *
+ * <p/>In practice, the accuracy of a BacthedThrottle skews off but can sometimes even be reasonable up to ten thousand
+ * hertz compared with 100 Hz for a {@link SleepThrottle}.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept throttling rate in operations per second.
+ * <tr><td> Inject short pauses, occasionaly, to fill out processing cycles to a specified rate.
+ * <tr><td> Check against a throttle speed without waiting.
+ * </table>
+ *
+ * @todo Should always round the log base 100 down to the nearest integer?
+ *
+ * @author Rupert Smith
+ */
+public class BatchedThrottle extends BaseThrottle
+{
+ /** Holds the batch size. */
+ int batchSize;
+
+ /** The call count within the current batch. */
+ long callCount;
+
+ /** Holds a sleep throttle configured to run at the batched rate. */
+ private Throttle batchRateThrottle = new SleepThrottle();
+
+ /**
+ * Specifies the throttling rate in operations per second.
+ *
+ * @param hertz The throttling rate in cycles per second.
+ */
+ public void setRate(float hertz)
+ {
+ // Pass the rate unaltered down to the base implementation, for the check method.
+ super.setRate(hertz);
+
+ // Log base 10 over 2 is used here to get a feel for what power of 100 the total rate is.
+ // As the total rate goes up the powers of 100 the batch size goes up by powers of 100 to keep the
+ // throttle rate in the range 1 to 100.
+ int x = (int) (Math.log10(hertz) / 2);
+ batchSize = (int) Math.pow(100, x);
+ float throttleRate = hertz / batchSize;
+
+ // Reset the call count.
+ callCount = 0;
+
+ // Set the sleep throttle wrapped implementation at a rate within its abilities.
+ batchRateThrottle.setRate(throttleRate);
+ }
+
+ /**
+ * Throttle calls to this method to the rate specified by the {@link #setRate(float)} method.
+ */
+ public void throttle()
+ {
+ if ((callCount++ % batchSize) == 0)
+ {
+ batchRateThrottle.throttle();
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
index fe1e044e67..1c1c146361 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/DurationTestDecorator.java
@@ -1,199 +1,199 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import org.apache.log4j.Logger;
-
-import java.util.Timer;
-import java.util.TimerTask;
-
-/**
- * A test decorator that runs a test repeatedly until a specified length of time has passed.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Repeatedly run a test for a fixed length of time.
- * </table>
- *
- * @todo The count of the number of tests run is an important number to keep. Also num passed/error/failed is also
- * important to record. What to do with these numbers? They are already logged to the test listeners.
- *
- * @todo The duration test runner wraps on top of size, repeat or thread wrappers, need a way for it to tell
- * TKTestResult when the duration is up, so that it can terminate any repeats in progress. It should end
- * as soon as possible once the test method exits.
- *
- * @author Rupert Smith
- */
-public class DurationTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(DurationTestDecorator.class);
-
- /** The test to run. */
- private Test test;
-
- /** The length of time to run the test for. */
- private long duration;
-
- /** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
- private boolean shutdown = false;
-
- /**
- * Creates an active test with default multiplier (1).
- *
- * @param test The target test.
- */
- public DurationTestDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Creates active test with default multiplier (1).
- *
- * @param test The target test.
- * @param duration The duration in milliseconds.
- */
- public DurationTestDecorator(WrappedSuiteTestDecorator test, long duration)
- {
- super(test);
-
- // log.debug("public DurationTestDecorator(Test \"" + test + "\", long " + duration + "): called");
-
- this.test = test;
- this.duration = duration;
- }
-
- /**
- * Runs the test repeatedly for the fixed duration.
- *
- * @param testResult The the results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- log.debug("public void run(TestResult testResult): called");
-
- // Cast the test result to expose it as a TKTestResult if the test is running under the TKTestRunner.
- TKTestResult tkTestResult = null;
-
- if (testResult instanceof TKTestResult)
- {
- tkTestResult = (TKTestResult) testResult;
- }
-
- // Work out when the test should end.
- long now = System.nanoTime();
- long end = (duration * 1000000) + now;
-
- // If running under the TKTestRunner, set up a timer to notify the test framework when the test reaches its
- // completion time.
- Timer durationTimer = null;
-
- if (tkTestResult != null)
- {
- log.debug("Creating duration timer.");
-
- durationTimer = new Timer();
- durationTimer.schedule(new DurationTimerTask((TKTestResult) testResult), duration);
- }
-
- // Run the test until the duration times out or the shutdown flag is set. The test method may not exit until
- // interrupted in some cases, in which case the timer will do the interrupting.
- while ((now < end) && !shutdown)
- {
- test.run(testResult);
-
- now = System.nanoTime();
- }
-
- // Clean up any timer that was used.
- if (durationTimer != null)
- {
- log.debug("Cancelling duration timer.");
-
- durationTimer.cancel();
- }
- }
-
- /**
- * Supplies the shutdown hook. This shutdown hook does not call {@link TKTestResult#shutdownNow()} because the
- * {@link ScaledTestDecorator} already takes care of that.
- *
- * @return The shut down hook.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- // log.debug("DurationTestDecorator::ShutdownHook: called");
-
- // Set the shutdown flag so that no new tests are started.
- shutdown = true;
- }
- });
- }
-
- /**
- * DurationTimerTask is a timer task that is configured, upon expiry of its timer, to invoke
- * {@link TKTestResult#shutdownNow()}, for the test result object on which it is set. It also sets
- * the {@link DurationTestDecorator#shutdown} flag to indicate that no new tests should be run.
- *
- * <p/>The test loop implemented by DurationTestDecorator checks that the duration has not expired, on each
- * test case that it runs. However, it is possible to write test cases that never return until explicitly
- * interrupted by the test framework. This timer task exists to notify the test framework
- */
- private class DurationTimerTask extends TimerTask
- {
- /** Used for debugging purposes. */
- private final Logger log = Logger.getLogger(DurationTimerTask.class);
-
- /** Holds the test result for the test to which a duration limit is being applied. */
- TKTestResult testResult;
-
- /**
- * Creates a duration limit timer which will notify the specified test result when the duration has
- * expired.
- *
- * @param testResult The test result to notify upon expiry of the test duration.
- */
- public DurationTimerTask(TKTestResult testResult)
- {
- this.testResult = testResult;
- }
-
- /**
- * The action to be performed by this timer task.
- */
- public void run()
- {
- log.debug("public void run(): called");
-
- shutdown = true;
- testResult.shutdownNow();
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.log4j.Logger;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * A test decorator that runs a test repeatedly until a specified length of time has passed.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Repeatedly run a test for a fixed length of time.
+ * </table>
+ *
+ * @todo The count of the number of tests run is an important number to keep. Also num passed/error/failed is also
+ * important to record. What to do with these numbers? They are already logged to the test listeners.
+ *
+ * @todo The duration test runner wraps on top of size, repeat or thread wrappers, need a way for it to tell
+ * TKTestResult when the duration is up, so that it can terminate any repeats in progress. It should end
+ * as soon as possible once the test method exits.
+ *
+ * @author Rupert Smith
+ */
+public class DurationTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(DurationTestDecorator.class);
+
+ /** The test to run. */
+ private Test test;
+
+ /** The length of time to run the test for. */
+ private long duration;
+
+ /** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
+ private boolean shutdown = false;
+
+ /**
+ * Creates an active test with default multiplier (1).
+ *
+ * @param test The target test.
+ */
+ public DurationTestDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Creates active test with default multiplier (1).
+ *
+ * @param test The target test.
+ * @param duration The duration in milliseconds.
+ */
+ public DurationTestDecorator(WrappedSuiteTestDecorator test, long duration)
+ {
+ super(test);
+
+ // log.debug("public DurationTestDecorator(Test \"" + test + "\", long " + duration + "): called");
+
+ this.test = test;
+ this.duration = duration;
+ }
+
+ /**
+ * Runs the test repeatedly for the fixed duration.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ log.debug("public void run(TestResult testResult): called");
+
+ // Cast the test result to expose it as a TKTestResult if the test is running under the TKTestRunner.
+ TKTestResult tkTestResult = null;
+
+ if (testResult instanceof TKTestResult)
+ {
+ tkTestResult = (TKTestResult) testResult;
+ }
+
+ // Work out when the test should end.
+ long now = System.nanoTime();
+ long end = (duration * 1000000) + now;
+
+ // If running under the TKTestRunner, set up a timer to notify the test framework when the test reaches its
+ // completion time.
+ Timer durationTimer = null;
+
+ if (tkTestResult != null)
+ {
+ log.debug("Creating duration timer.");
+
+ durationTimer = new Timer();
+ durationTimer.schedule(new DurationTimerTask((TKTestResult) testResult), duration);
+ }
+
+ // Run the test until the duration times out or the shutdown flag is set. The test method may not exit until
+ // interrupted in some cases, in which case the timer will do the interrupting.
+ while ((now < end) && !shutdown)
+ {
+ test.run(testResult);
+
+ now = System.nanoTime();
+ }
+
+ // Clean up any timer that was used.
+ if (durationTimer != null)
+ {
+ log.debug("Cancelling duration timer.");
+
+ durationTimer.cancel();
+ }
+ }
+
+ /**
+ * Supplies the shutdown hook. This shutdown hook does not call {@link TKTestResult#shutdownNow()} because the
+ * {@link ScaledTestDecorator} already takes care of that.
+ *
+ * @return The shut down hook.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ // log.debug("DurationTestDecorator::ShutdownHook: called");
+
+ // Set the shutdown flag so that no new tests are started.
+ shutdown = true;
+ }
+ });
+ }
+
+ /**
+ * DurationTimerTask is a timer task that is configured, upon expiry of its timer, to invoke
+ * {@link TKTestResult#shutdownNow()}, for the test result object on which it is set. It also sets
+ * the {@link DurationTestDecorator#shutdown} flag to indicate that no new tests should be run.
+ *
+ * <p/>The test loop implemented by DurationTestDecorator checks that the duration has not expired, on each
+ * test case that it runs. However, it is possible to write test cases that never return until explicitly
+ * interrupted by the test framework. This timer task exists to notify the test framework
+ */
+ private class DurationTimerTask extends TimerTask
+ {
+ /** Used for debugging purposes. */
+ private final Logger log = Logger.getLogger(DurationTimerTask.class);
+
+ /** Holds the test result for the test to which a duration limit is being applied. */
+ TKTestResult testResult;
+
+ /**
+ * Creates a duration limit timer which will notify the specified test result when the duration has
+ * expired.
+ *
+ * @param testResult The test result to notify upon expiry of the test duration.
+ */
+ public DurationTimerTask(TKTestResult testResult)
+ {
+ this.testResult = testResult;
+ }
+
+ /**
+ * The action to be performed by this timer task.
+ */
+ public void run()
+ {
+ log.debug("public void run(): called");
+
+ shutdown = true;
+ testResult.shutdownNow();
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java
index ed792fcd5a..0804757dce 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/InstrumentedTest.java
@@ -1,66 +1,66 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-
-/**
- * An InstrumentedTest is one which can supply some additional instrumentation on top of the pass/fail/error behaviour
- * of normal junit tests. Tests implementing this interface must additionally supply information about how long they
- * took to run and how much memory they used.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Report test run time.
- * <tr><td> Report test memory usage.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface InstrumentedTest extends Test
-{
- /**
- * Reports how long the test took to run.
- *
- * @return The time in milliseconds that the test took to run.
- */
- public long getTestTime();
-
- /**
- * Reports the memory usage at the start of the test.
- *
- * @return The memory usage at the start of the test.
- */
- public long getTestStartMemory();
-
- /**
- * Reports the memory usage at the end of the test.
- *
- * @return The memory usage at the end of the test.
- */
- public long getTestEndMemory();
-
- /**
- * Resets the instrumentation values to zero, and nulls any references to held measurements so that the memory
- * can be reclaimed.
- */
- public void reset();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+
+/**
+ * An InstrumentedTest is one which can supply some additional instrumentation on top of the pass/fail/error behaviour
+ * of normal junit tests. Tests implementing this interface must additionally supply information about how long they
+ * took to run and how much memory they used.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Report test run time.
+ * <tr><td> Report test memory usage.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface InstrumentedTest extends Test
+{
+ /**
+ * Reports how long the test took to run.
+ *
+ * @return The time in milliseconds that the test took to run.
+ */
+ public long getTestTime();
+
+ /**
+ * Reports the memory usage at the start of the test.
+ *
+ * @return The memory usage at the start of the test.
+ */
+ public long getTestStartMemory();
+
+ /**
+ * Reports the memory usage at the end of the test.
+ *
+ * @return The memory usage at the end of the test.
+ */
+ public long getTestEndMemory();
+
+ /**
+ * Resets the instrumentation values to zero, and nulls any references to held measurements so that the memory
+ * can be reclaimed.
+ */
+ public void reset();
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java
index 2ffbcb5bb8..6727f6f152 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/NullResultPrinter.java
@@ -1,92 +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.junit.extensions;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-
-import junit.textui.ResultPrinter;
-
-import java.io.PrintStream;
-
-/**
- * A ResultPrinter that prints nothing. This exists, in order to provide a replacement to JUnit's ResultPrinter, which
- * is refered to directly by JUnit code, rather that as an abstracted TestListener. JUnit's text ui TestRunner must
- * have a ResultPrinter. This provides an implementation of it that prints nothing, so that a better mechanism can
- * be used for providing feedback to the console instead.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- *
- * @todo See todo in TKTestRunner about completely replacing the test ui runner. Doing things like this in order to
- * extend JUnit is not nice, and there needs to be a better way to do it. Delete this class and use a listener
- * instead.
- *
- * @author Rupert Smith
- */
-public class NullResultPrinter extends ResultPrinter
-{
- /**
- * Builds a fake ResultPrinter that prints nothing.
- *
- * @param writer The writer to send output to.
- */
- public NullResultPrinter(PrintStream writer)
- {
- super(writer);
- }
-
- /**
- * Does nothing.
- *
- * @param test Ignored.
- * @param t Ignored.
- */
- public void addError(Test test, Throwable t)
- { }
-
- /**
- * Does nothing.
- *
- * @param test Ignored.
- * @param t Ignored.
- */
- public void addFailure(Test test, AssertionFailedError t)
- { }
-
- /**
- * Does nothing.
- *
- * @param test Ignored.
- */
- public void endTest(Test test)
- { }
-
- /**
- * Does nothing.
- *
- * @param test Ignored.
- */
- public void startTest(Test test)
- { }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+
+import junit.textui.ResultPrinter;
+
+import java.io.PrintStream;
+
+/**
+ * A ResultPrinter that prints nothing. This exists, in order to provide a replacement to JUnit's ResultPrinter, which
+ * is refered to directly by JUnit code, rather that as an abstracted TestListener. JUnit's text ui TestRunner must
+ * have a ResultPrinter. This provides an implementation of it that prints nothing, so that a better mechanism can
+ * be used for providing feedback to the console instead.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo See todo in TKTestRunner about completely replacing the test ui runner. Doing things like this in order to
+ * extend JUnit is not nice, and there needs to be a better way to do it. Delete this class and use a listener
+ * instead.
+ *
+ * @author Rupert Smith
+ */
+public class NullResultPrinter extends ResultPrinter
+{
+ /**
+ * Builds a fake ResultPrinter that prints nothing.
+ *
+ * @param writer The writer to send output to.
+ */
+ public NullResultPrinter(PrintStream writer)
+ {
+ super(writer);
+ }
+
+ /**
+ * Does nothing.
+ *
+ * @param test Ignored.
+ * @param t Ignored.
+ */
+ public void addError(Test test, Throwable t)
+ { }
+
+ /**
+ * Does nothing.
+ *
+ * @param test Ignored.
+ * @param t Ignored.
+ */
+ public void addFailure(Test test, AssertionFailedError t)
+ { }
+
+ /**
+ * Does nothing.
+ *
+ * @param test Ignored.
+ */
+ public void endTest(Test test)
+ { }
+
+ /**
+ * Does nothing.
+ *
+ * @param test Ignored.
+ */
+ public void startTest(Test test)
+ { }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java
index 60ec156354..2c207635c7 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ParameterVariationTestDecorator.java
@@ -1,172 +1,172 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.TestResult;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.util.MathUtils;
-
-/**
- * ParameterVariationTestDecorator is a test decorator that runs a test repeatedly under all permutations of its
- * test parameters.
- *
- * a set of integer parameters and a repeat count are specified, then each test is run for the repeat count at each
- * integer parameter.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Repeat a test for each of a set of integer parameters. <td> {@link org.apache.qpid.junit.extensions.TKTestResult}
- * <tr><td> Repeat a test multiple times.
- * <tr><td>
- * </table>
- *
- * @author Rupert Smith
- */
-public class ParameterVariationTestDecorator extends WrappedSuiteTestDecorator
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(ParameterVariationTestDecorator.class);
-
- /** The int size parameters to run the test with. */
- private int[] params;
-
- /** The number of times the whole test should be repeated. */
- private int repeat;
-
- /**
- * Creates an asymptotic test decorator that wraps a test with repeats and a set of integer 'size' paramters
- * to call the test with.
- *
- * @param test The test to wrap.
- * @param params The integer 'size' parameters.
- * @param repeat The number of times to repeat the test.
- */
- public ParameterVariationTestDecorator(WrappedSuiteTestDecorator test, int[] params, int repeat)
- {
- super(test);
-
- log.debug("public AsymptoticTestDecorator(Test \"" + test + "\", int[] "
- + ((params == null) ? null : MathUtils.printArray(params)) + ", int " + repeat + "): called");
-
- this.params = params;
- this.repeat = repeat;
- }
-
- /**
- * Creates a new AsymptoticTestDecorator object.
- *
- * @param test The test to decorate.
- * @param start The starting asymptotic integer parameter value.
- * @param end The ending asymptotic integer parameter value.
- * @param step The increment size to move from the start to end values by.
- * @param repeat The number of times to repeat the test at each step of the cycle.
- */
- public ParameterVariationTestDecorator(WrappedSuiteTestDecorator test, int start, int end, int step, int repeat)
- {
- super(test);
-
- if (start < 0)
- {
- throw new IllegalArgumentException("Start must be >= 0");
- }
-
- if (end < start)
- {
- throw new IllegalArgumentException("End must be >= start");
- }
-
- if (step < 1)
- {
- throw new IllegalArgumentException("Step must be >= 1");
- }
-
- if (repeat < 1)
- {
- throw new IllegalArgumentException("Repeat must be >= 1");
- }
-
- // Generate the sequence.
- params = new int[((end - start) / step) + 1];
- int i = 0;
- for (int n = start; n <= end; n += step)
- {
- params[i++] = n;
- }
-
- this.repeat = repeat;
- }
-
- /**
- * Runs the test repeatedly for each value of the int parameter specified and for the correct number of test
- * repeats.
- *
- * @param result The test result object that the tests will indicate their results to. This is also used
- * to pass the int parameter from this class to the decorated test class.
- */
- public void run(TestResult result)
- {
- log.debug("public void run(TestResult result): called");
-
- if (!(result instanceof TKTestResult))
- {
- throw new IllegalArgumentException("AsymptoticTestDecorator only works with TKTestResult");
- }
-
- // Cast the test result into a TKTestResult to place the current parameter into.
- TKTestResult tkResult = (TKTestResult) result;
-
- log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
- log.debug("repeat = " + repeat);
-
- for (int n : params)
- {
- for (int j = 0; j < repeat; j++)
- {
- log.debug("n = " + n);
-
- // Set the integer parameter in the TKTestResult to be passed to the tests.
- tkResult.setN(n);
-
- if (tkResult.shouldStop())
- {
- log.debug("tkResult.shouldStop = " + true);
-
- break;
- }
-
- log.debug("Calling super#run");
- super.run(tkResult);
- }
- }
- }
-
- /**
- * Prints out the name of this test with the string "(parameterized)" appended onto it for debugging purposes.
- *
- * @return The name of this test with the string "(parameterized)" appended onto it.
- */
- public String toString()
- {
- return super.toString() + "(parameterized)";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.TestResult;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.util.MathUtils;
+
+/**
+ * ParameterVariationTestDecorator is a test decorator that runs a test repeatedly under all permutations of its
+ * test parameters.
+ *
+ * a set of integer parameters and a repeat count are specified, then each test is run for the repeat count at each
+ * integer parameter.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Repeat a test for each of a set of integer parameters. <td> {@link org.apache.qpid.junit.extensions.TKTestResult}
+ * <tr><td> Repeat a test multiple times.
+ * <tr><td>
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ParameterVariationTestDecorator extends WrappedSuiteTestDecorator
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(ParameterVariationTestDecorator.class);
+
+ /** The int size parameters to run the test with. */
+ private int[] params;
+
+ /** The number of times the whole test should be repeated. */
+ private int repeat;
+
+ /**
+ * Creates an asymptotic test decorator that wraps a test with repeats and a set of integer 'size' paramters
+ * to call the test with.
+ *
+ * @param test The test to wrap.
+ * @param params The integer 'size' parameters.
+ * @param repeat The number of times to repeat the test.
+ */
+ public ParameterVariationTestDecorator(WrappedSuiteTestDecorator test, int[] params, int repeat)
+ {
+ super(test);
+
+ log.debug("public AsymptoticTestDecorator(Test \"" + test + "\", int[] "
+ + ((params == null) ? null : MathUtils.printArray(params)) + ", int " + repeat + "): called");
+
+ this.params = params;
+ this.repeat = repeat;
+ }
+
+ /**
+ * Creates a new AsymptoticTestDecorator object.
+ *
+ * @param test The test to decorate.
+ * @param start The starting asymptotic integer parameter value.
+ * @param end The ending asymptotic integer parameter value.
+ * @param step The increment size to move from the start to end values by.
+ * @param repeat The number of times to repeat the test at each step of the cycle.
+ */
+ public ParameterVariationTestDecorator(WrappedSuiteTestDecorator test, int start, int end, int step, int repeat)
+ {
+ super(test);
+
+ if (start < 0)
+ {
+ throw new IllegalArgumentException("Start must be >= 0");
+ }
+
+ if (end < start)
+ {
+ throw new IllegalArgumentException("End must be >= start");
+ }
+
+ if (step < 1)
+ {
+ throw new IllegalArgumentException("Step must be >= 1");
+ }
+
+ if (repeat < 1)
+ {
+ throw new IllegalArgumentException("Repeat must be >= 1");
+ }
+
+ // Generate the sequence.
+ params = new int[((end - start) / step) + 1];
+ int i = 0;
+ for (int n = start; n <= end; n += step)
+ {
+ params[i++] = n;
+ }
+
+ this.repeat = repeat;
+ }
+
+ /**
+ * Runs the test repeatedly for each value of the int parameter specified and for the correct number of test
+ * repeats.
+ *
+ * @param result The test result object that the tests will indicate their results to. This is also used
+ * to pass the int parameter from this class to the decorated test class.
+ */
+ public void run(TestResult result)
+ {
+ log.debug("public void run(TestResult result): called");
+
+ if (!(result instanceof TKTestResult))
+ {
+ throw new IllegalArgumentException("AsymptoticTestDecorator only works with TKTestResult");
+ }
+
+ // Cast the test result into a TKTestResult to place the current parameter into.
+ TKTestResult tkResult = (TKTestResult) result;
+
+ log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
+ log.debug("repeat = " + repeat);
+
+ for (int n : params)
+ {
+ for (int j = 0; j < repeat; j++)
+ {
+ log.debug("n = " + n);
+
+ // Set the integer parameter in the TKTestResult to be passed to the tests.
+ tkResult.setN(n);
+
+ if (tkResult.shouldStop())
+ {
+ log.debug("tkResult.shouldStop = " + true);
+
+ break;
+ }
+
+ log.debug("Calling super#run");
+ super.run(tkResult);
+ }
+ }
+ }
+
+ /**
+ * Prints out the name of this test with the string "(parameterized)" appended onto it for debugging purposes.
+ *
+ * @return The name of this test with the string "(parameterized)" appended onto it.
+ */
+ public String toString()
+ {
+ return super.toString() + "(parameterized)";
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
index f5e3e1a758..e0af22cfb7 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ScaledTestDecorator.java
@@ -1,375 +1,375 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-/**
- * A test decorator that runs a test many times simultaneously in many threads.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Clone a test run into many threads and run them simultaneously.
- * <tr><td> Inform the test results of the start and end of each concurrent test batch. <td> {@link TKTestResult}
- * <tr><td> Inform the test results of the concurrency level. <td> {@link TKTestResult}
- * </table>
- *
- * @author Rupert Smith
- */
-public class ScaledTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable // TestDecorator
-{
- /** Used for logging. */
- // private static final Logger log = Logger.getLogger(ScaledTestDecorator.class);
-
- /** Determines how long to wait for tests to cleanly exit on shutdown. */
- private static final long SHUTDOWN_PAUSE = 3000;
-
- /**
- * The stress levels or numbers of simultaneous threads to run the test in. The test is repeated at each of
- * the concurrency levels specified here. Defaults to 1 thread.
- */
- private int[] threads = new int[] { 1 };
-
- /** Used to hold the number of tests currently being run in parallel. */
- private int concurrencyLevel;
-
- /** The test to run. */
- private WrappedSuiteTestDecorator test;
-
- /**
- * Used to hold the current {@link TKTestResult} for the tests currently being run. This is made available so that
- * the shutdown hook can ask it to cleanly end the current tests in the event of a shutdown.
- */
- private TKTestResult currentTestResult;
-
- /** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
- private boolean shutdown = false;
-
- /**
- * Creates an active test with default multiplier (1).
- *
- * @param test The target test.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Creates a concurrently scaled test with the specified number of threads.
- *
- * @param test The target test.
- * @param numThreads The stress level.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test, int numThreads)
- {
- this(test, new int[] { numThreads });
- }
-
- /**
- * Creates a concurrently scaled test with the specified thread levels, the test is repeated at each level.
- *
- * @param test The target test.
- * @param threads The concurrency levels.
- */
- public ScaledTestDecorator(WrappedSuiteTestDecorator test, int[] threads)
- {
- super(test);
-
- /*log.debug("public ScaledTestDecorator(WrappedSuiteTestDecorator test = \"" + test + "\", int[] threads = "
- + MathUtils.printArray(threads) + "): called");*/
-
- this.test = test;
- this.threads = threads;
- }
-
- /**
- * Runs the test simultaneously in at the specified concurrency levels.
- *
- * @param testResult The results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- // log.debug("public void run(TestResult testResult = " + testResult + "): called");
-
- // Loop through all of the specified concurrent levels for the test, provided shutdown has not been called.
- for (int i = 0; (i < threads.length) && !shutdown; i++)
- {
- // Get the number of threads for this run.
- int numThreads = threads[i];
-
- // Create test thread handlers for all the threads.
- TestThreadHandler[] threadHandlers = new TestThreadHandler[numThreads];
-
- // Create a cyclic barrier for the test threads to synch their setups and teardowns on.
- CyclicBarrier barrier = new CyclicBarrier(numThreads);
-
- // Set up the test thread handlers to output results to the same test results object.
- for (int j = 0; j < numThreads; j++)
- {
- threadHandlers[j] = new TestThreadHandler(testResult, test, barrier);
- }
-
- // Ensure the concurrency level statistic is set up correctly.
- concurrencyLevel = numThreads;
-
- // Begin batch.
- if (testResult instanceof TKTestResult)
- {
- TKTestResult tkResult = (TKTestResult) testResult;
- // tkResult.notifyStartBatch();
- tkResult.setConcurrencyLevel(numThreads);
-
- // Set the test result for the currently running tests, so that the shutdown hook can call it if necessary.
- currentTestResult = tkResult;
- }
-
- // Run all the tests and wait for them all to finish.
- executeAndWaitForRunnables(threadHandlers);
-
- // Clear the test result for the currently running tests.
- currentTestResult = null;
-
- // End batch.
- if (testResult instanceof TKTestResult)
- {
- TKTestResult tkResult = (TKTestResult) testResult;
- tkResult.notifyEndBatch();
- }
-
- // Clear up all the test threads, they hold references to their associated TestResult object and Test object,
- // which may prevent them from being garbage collected as the TestResult and Test objects are long lived.
- for (int j = 0; j < numThreads; j++)
- {
- threadHandlers[j].testResult = null;
- threadHandlers[j].test = null;
- threadHandlers[j] = null;
- }
- }
- }
-
- /**
- * Reports the number of tests that the scaled decorator is currently running concurrently.
- *
- * @return The number of tests that the scaled decorator is currently running concurrently.
- */
- public int getConcurrencyLevel()
- {
- return concurrencyLevel;
- }
-
- /**
- * Executes all of the specifed runnable using the thread pool and waits for them all to complete.
- *
- * @param runnables The set of runnables to execute concurrently.
- */
- private void executeAndWaitForRunnables(Runnable[] runnables)
- {
- int numThreads = runnables.length;
-
- // Used to keep track of the test threads in order to know when they have all completed.
- Thread[] threads = new Thread[numThreads];
-
- // Create all the test threads.
- for (int j = 0; j < numThreads; j++)
- {
- threads[j] = new Thread(runnables[j]);
- }
-
- // Start all the test threads.
- for (int j = 0; j < numThreads; j++)
- {
- threads[j].start();
- }
-
- // Wait for all the test threads to complete.
- for (int j = 0; j < numThreads; j++)
- {
- try
- {
- threads[j].join();
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- }
- }
-
- /**
- * Supplies the shut-down hook.
- *
- * @return The shut-down hook.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- // log.debug("ScaledTestDecorator::ShutdownHook: called");
-
- // Set the shutdown flag so that no new tests are started.
- shutdown = true;
-
- // Check if tests are currently running, and ask them to complete as soon as possible. Allow
- // a short pause for this to happen.
- TKTestResult testResult = currentTestResult;
-
- if (testResult != null)
- {
- // log.debug("There is a test result currently running tests, asking it to terminate ASAP.");
- testResult.shutdownNow();
-
- try
- {
- Thread.sleep(SHUTDOWN_PAUSE);
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- }
- }
- });
- }
-
- /**
- * Prints a string summarizing this test decorator, mainly for debugging purposes.
- *
- * @return String representation for debugging purposes.
- */
- public String toString()
- {
- return "ScaledTestDecorator: [ test = " + test + ", concurrencyLevel = " + concurrencyLevel + " ]";
- }
-
- /**
- * TestThreadHandler is a runnable used to execute a test in. This is static to avoid implicit 'this' reference to
- * the longer lived ScaledTestDecorator class. The scaled test decorator may execute many repeats but creates fresh
- * handlers for each one. It re-uses the threads in a pool but does not re-use these handlers.
- */
- private static class TestThreadHandler implements Runnable
- {
- /** The test result object for the test to be run with. */
- TestResult testResult;
-
- /** The test to run. */
- WrappedSuiteTestDecorator test;
-
- /** Holds the cyclic barrier to synchronize on the end of the setups and before the tear downs. */
- CyclicBarrier barrier;
-
- /**
- * Creates a new TestThreadHandler object.
- *
- * @param testResult The test result object for the test to be run with.
- * @param test The test to run in a sperate thread.
- * @param barrier The barrier implementation to use to synchronize per-thread setup completion and test
- * completion before moving on through the setup, test, teardown phases. The barrier should
- * be configured for the number of test threads.
- */
- TestThreadHandler(TestResult testResult, WrappedSuiteTestDecorator test, CyclicBarrier barrier)
- {
- this.testResult = testResult;
- this.test = test;
- this.barrier = barrier;
- }
-
- /**
- * Runs the test associated with this pool.
- */
- public void run()
- {
- try
- {
- // Call setup on all underlying tests in the suite that are thread aware.
- for (Test childTest : test.getAllUnderlyingTests())
- {
- // Check that the test is concurrency aware, so provides a setup method to call.
- if (childTest instanceof TestThreadAware)
- {
- // Call the tests per thread setup.
- TestThreadAware setupTest = (TestThreadAware) childTest;
- setupTest.threadSetUp();
- }
- }
-
- // Wait until all test threads have completed their setups.
- barrier.await();
-
- // Start timing the test batch, only after thread setups have completed.
- if (testResult instanceof TKTestResult)
- {
- ((TKTestResult) testResult).notifyStartBatch();
- }
-
- // Run the tests.
- test.run(testResult);
-
- // Wait unitl all test threads have completed their tests.
- barrier.await();
-
- // Call tear down on all underlying tests in the suite that are thread aware.
- for (Test childTest : test.getAllUnderlyingTests())
- {
- // Check that the test is concurrency aware, so provides a teardown method to call.
- if (childTest instanceof TestThreadAware)
- {
- // Call the tests per thread tear down.
- TestThreadAware setupTest = (TestThreadAware) childTest;
- setupTest.threadTearDown();
- }
- }
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted state of the thread.
- Thread.currentThread().interrupt();
- }
- catch (BrokenBarrierException e)
- {
- // Set the interrupted state on the thread. The BrokenBarrierException may be caused where one thread
- // waiting for the barrier is interrupted, causing the remaining threads correctly waiting on the
- // barrier to fail. This condition is expected during test interruptions, and the response to it is to
- // interrupt all the other threads running in the same scaled test.
- Thread.currentThread().interrupt();
- }
- }
-
- /**
- * Prints the name of the test for debugging purposes.
- *
- * @return The name of the test.
- */
- public String toString()
- {
- return "ScaledTestDecorator: [test = \"" + test + "\"]";
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+/**
+ * A test decorator that runs a test many times simultaneously in many threads.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Clone a test run into many threads and run them simultaneously.
+ * <tr><td> Inform the test results of the start and end of each concurrent test batch. <td> {@link TKTestResult}
+ * <tr><td> Inform the test results of the concurrency level. <td> {@link TKTestResult}
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ScaledTestDecorator extends WrappedSuiteTestDecorator implements ShutdownHookable // TestDecorator
+{
+ /** Used for logging. */
+ // private static final Logger log = Logger.getLogger(ScaledTestDecorator.class);
+
+ /** Determines how long to wait for tests to cleanly exit on shutdown. */
+ private static final long SHUTDOWN_PAUSE = 3000;
+
+ /**
+ * The stress levels or numbers of simultaneous threads to run the test in. The test is repeated at each of
+ * the concurrency levels specified here. Defaults to 1 thread.
+ */
+ private int[] threads = new int[] { 1 };
+
+ /** Used to hold the number of tests currently being run in parallel. */
+ private int concurrencyLevel;
+
+ /** The test to run. */
+ private WrappedSuiteTestDecorator test;
+
+ /**
+ * Used to hold the current {@link TKTestResult} for the tests currently being run. This is made available so that
+ * the shutdown hook can ask it to cleanly end the current tests in the event of a shutdown.
+ */
+ private TKTestResult currentTestResult;
+
+ /** Flag set by the shutdown hook. This decorator will not start any new tests when this is set. */
+ private boolean shutdown = false;
+
+ /**
+ * Creates an active test with default multiplier (1).
+ *
+ * @param test The target test.
+ */
+ public ScaledTestDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Creates a concurrently scaled test with the specified number of threads.
+ *
+ * @param test The target test.
+ * @param numThreads The stress level.
+ */
+ public ScaledTestDecorator(WrappedSuiteTestDecorator test, int numThreads)
+ {
+ this(test, new int[] { numThreads });
+ }
+
+ /**
+ * Creates a concurrently scaled test with the specified thread levels, the test is repeated at each level.
+ *
+ * @param test The target test.
+ * @param threads The concurrency levels.
+ */
+ public ScaledTestDecorator(WrappedSuiteTestDecorator test, int[] threads)
+ {
+ super(test);
+
+ /*log.debug("public ScaledTestDecorator(WrappedSuiteTestDecorator test = \"" + test + "\", int[] threads = "
+ + MathUtils.printArray(threads) + "): called");*/
+
+ this.test = test;
+ this.threads = threads;
+ }
+
+ /**
+ * Runs the test simultaneously in at the specified concurrency levels.
+ *
+ * @param testResult The results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ // log.debug("public void run(TestResult testResult = " + testResult + "): called");
+
+ // Loop through all of the specified concurrent levels for the test, provided shutdown has not been called.
+ for (int i = 0; (i < threads.length) && !shutdown; i++)
+ {
+ // Get the number of threads for this run.
+ int numThreads = threads[i];
+
+ // Create test thread handlers for all the threads.
+ TestThreadHandler[] threadHandlers = new TestThreadHandler[numThreads];
+
+ // Create a cyclic barrier for the test threads to synch their setups and teardowns on.
+ CyclicBarrier barrier = new CyclicBarrier(numThreads);
+
+ // Set up the test thread handlers to output results to the same test results object.
+ for (int j = 0; j < numThreads; j++)
+ {
+ threadHandlers[j] = new TestThreadHandler(testResult, test, barrier);
+ }
+
+ // Ensure the concurrency level statistic is set up correctly.
+ concurrencyLevel = numThreads;
+
+ // Begin batch.
+ if (testResult instanceof TKTestResult)
+ {
+ TKTestResult tkResult = (TKTestResult) testResult;
+ // tkResult.notifyStartBatch();
+ tkResult.setConcurrencyLevel(numThreads);
+
+ // Set the test result for the currently running tests, so that the shutdown hook can call it if necessary.
+ currentTestResult = tkResult;
+ }
+
+ // Run all the tests and wait for them all to finish.
+ executeAndWaitForRunnables(threadHandlers);
+
+ // Clear the test result for the currently running tests.
+ currentTestResult = null;
+
+ // End batch.
+ if (testResult instanceof TKTestResult)
+ {
+ TKTestResult tkResult = (TKTestResult) testResult;
+ tkResult.notifyEndBatch();
+ }
+
+ // Clear up all the test threads, they hold references to their associated TestResult object and Test object,
+ // which may prevent them from being garbage collected as the TestResult and Test objects are long lived.
+ for (int j = 0; j < numThreads; j++)
+ {
+ threadHandlers[j].testResult = null;
+ threadHandlers[j].test = null;
+ threadHandlers[j] = null;
+ }
+ }
+ }
+
+ /**
+ * Reports the number of tests that the scaled decorator is currently running concurrently.
+ *
+ * @return The number of tests that the scaled decorator is currently running concurrently.
+ */
+ public int getConcurrencyLevel()
+ {
+ return concurrencyLevel;
+ }
+
+ /**
+ * Executes all of the specifed runnable using the thread pool and waits for them all to complete.
+ *
+ * @param runnables The set of runnables to execute concurrently.
+ */
+ private void executeAndWaitForRunnables(Runnable[] runnables)
+ {
+ int numThreads = runnables.length;
+
+ // Used to keep track of the test threads in order to know when they have all completed.
+ Thread[] threads = new Thread[numThreads];
+
+ // Create all the test threads.
+ for (int j = 0; j < numThreads; j++)
+ {
+ threads[j] = new Thread(runnables[j]);
+ }
+
+ // Start all the test threads.
+ for (int j = 0; j < numThreads; j++)
+ {
+ threads[j].start();
+ }
+
+ // Wait for all the test threads to complete.
+ for (int j = 0; j < numThreads; j++)
+ {
+ try
+ {
+ threads[j].join();
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted state of the thread.
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * Supplies the shut-down hook.
+ *
+ * @return The shut-down hook.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ // log.debug("ScaledTestDecorator::ShutdownHook: called");
+
+ // Set the shutdown flag so that no new tests are started.
+ shutdown = true;
+
+ // Check if tests are currently running, and ask them to complete as soon as possible. Allow
+ // a short pause for this to happen.
+ TKTestResult testResult = currentTestResult;
+
+ if (testResult != null)
+ {
+ // log.debug("There is a test result currently running tests, asking it to terminate ASAP.");
+ testResult.shutdownNow();
+
+ try
+ {
+ Thread.sleep(SHUTDOWN_PAUSE);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted state of the thread.
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * Prints a string summarizing this test decorator, mainly for debugging purposes.
+ *
+ * @return String representation for debugging purposes.
+ */
+ public String toString()
+ {
+ return "ScaledTestDecorator: [ test = " + test + ", concurrencyLevel = " + concurrencyLevel + " ]";
+ }
+
+ /**
+ * TestThreadHandler is a runnable used to execute a test in. This is static to avoid implicit 'this' reference to
+ * the longer lived ScaledTestDecorator class. The scaled test decorator may execute many repeats but creates fresh
+ * handlers for each one. It re-uses the threads in a pool but does not re-use these handlers.
+ */
+ private static class TestThreadHandler implements Runnable
+ {
+ /** The test result object for the test to be run with. */
+ TestResult testResult;
+
+ /** The test to run. */
+ WrappedSuiteTestDecorator test;
+
+ /** Holds the cyclic barrier to synchronize on the end of the setups and before the tear downs. */
+ CyclicBarrier barrier;
+
+ /**
+ * Creates a new TestThreadHandler object.
+ *
+ * @param testResult The test result object for the test to be run with.
+ * @param test The test to run in a sperate thread.
+ * @param barrier The barrier implementation to use to synchronize per-thread setup completion and test
+ * completion before moving on through the setup, test, teardown phases. The barrier should
+ * be configured for the number of test threads.
+ */
+ TestThreadHandler(TestResult testResult, WrappedSuiteTestDecorator test, CyclicBarrier barrier)
+ {
+ this.testResult = testResult;
+ this.test = test;
+ this.barrier = barrier;
+ }
+
+ /**
+ * Runs the test associated with this pool.
+ */
+ public void run()
+ {
+ try
+ {
+ // Call setup on all underlying tests in the suite that are thread aware.
+ for (Test childTest : test.getAllUnderlyingTests())
+ {
+ // Check that the test is concurrency aware, so provides a setup method to call.
+ if (childTest instanceof TestThreadAware)
+ {
+ // Call the tests per thread setup.
+ TestThreadAware setupTest = (TestThreadAware) childTest;
+ setupTest.threadSetUp();
+ }
+ }
+
+ // Wait until all test threads have completed their setups.
+ barrier.await();
+
+ // Start timing the test batch, only after thread setups have completed.
+ if (testResult instanceof TKTestResult)
+ {
+ ((TKTestResult) testResult).notifyStartBatch();
+ }
+
+ // Run the tests.
+ test.run(testResult);
+
+ // Wait unitl all test threads have completed their tests.
+ barrier.await();
+
+ // Call tear down on all underlying tests in the suite that are thread aware.
+ for (Test childTest : test.getAllUnderlyingTests())
+ {
+ // Check that the test is concurrency aware, so provides a teardown method to call.
+ if (childTest instanceof TestThreadAware)
+ {
+ // Call the tests per thread tear down.
+ TestThreadAware setupTest = (TestThreadAware) childTest;
+ setupTest.threadTearDown();
+ }
+ }
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted state of the thread.
+ Thread.currentThread().interrupt();
+ }
+ catch (BrokenBarrierException e)
+ {
+ // Set the interrupted state on the thread. The BrokenBarrierException may be caused where one thread
+ // waiting for the barrier is interrupted, causing the remaining threads correctly waiting on the
+ // barrier to fail. This condition is expected during test interruptions, and the response to it is to
+ // interrupt all the other threads running in the same scaled test.
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "ScaledTestDecorator: [test = \"" + test + "\"]";
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java
index 0e8e1879b6..e462145d7d 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskAware.java
@@ -1,55 +1,55 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-/**
- * SetupTaskAware is an interface that tests that can accept injectable setup tasks may implement. Typically this
- * is used by configurable decorator stack to inject setup tasks into tests. It is then up to the test case to run
- * the tasks in the setup or threadSetup methods as it chooses.
- *
- * <p/>Set up tasks should be chained so that they are executed in the order that they are applied. Tear down tasks
- * should be chained so that they are executed in the reverse order to which they are applied. That way the set up and
- * tear down tasks act as a 'task' stack, with nested setups and tear downs.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities.
- * <tr><td> Handle injection of set up tasks.
- * <tr><td> Handle injection of tear down tasks.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface SetupTaskAware
-{
- /**
- * Adds the specified task to the tests setup.
- *
- * @param task The task to add to the tests setup.
- */
- public void chainSetupTask(Runnable task);
-
- /**
- * Adds the specified task to the tests tear down.
- *
- * @param task The task to add to the tests tear down.
- */
- public void chainTearDownTask(Runnable task);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * SetupTaskAware is an interface that tests that can accept injectable setup tasks may implement. Typically this
+ * is used by configurable decorator stack to inject setup tasks into tests. It is then up to the test case to run
+ * the tasks in the setup or threadSetup methods as it chooses.
+ *
+ * <p/>Set up tasks should be chained so that they are executed in the order that they are applied. Tear down tasks
+ * should be chained so that they are executed in the reverse order to which they are applied. That way the set up and
+ * tear down tasks act as a 'task' stack, with nested setups and tear downs.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities.
+ * <tr><td> Handle injection of set up tasks.
+ * <tr><td> Handle injection of tear down tasks.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface SetupTaskAware
+{
+ /**
+ * Adds the specified task to the tests setup.
+ *
+ * @param task The task to add to the tests setup.
+ */
+ public void chainSetupTask(Runnable task);
+
+ /**
+ * Adds the specified task to the tests tear down.
+ *
+ * @param task The task to add to the tests tear down.
+ */
+ public void chainTearDownTask(Runnable task);
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java
index 00736c59e5..b91ce41ad3 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SetupTaskHandler.java
@@ -1,92 +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.junit.extensions;
-
-import org.apache.qpid.junit.extensions.util.StackQueue;
-
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * SetupTaskHandler implements a task stack. It can be used, by delegation, as a base implementation for tests that want
- * to have configurable setup/teardown task stacks. Typically it is up to the test implementation to decide whether the
- * stack is executed in the setup/teardown methods or in the threadSetup/threadTeaddown methods.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Handle injection of set up tasks.
- * <tr><td> Handle injection of tear down tasks.
- * <tr><td> Run set up tasks in chain order.
- * <tr><td> Run tear down tasks in reverse chain order.
- * </table>
- *
- * @author Rupert Smith
- */
-public class SetupTaskHandler implements SetupTaskAware
-{
- /** Holds the set up tasks. */
- Queue<Runnable> setups = new LinkedList<Runnable>();
-
- /** Holds the tear down tasks. */
- Queue<Runnable> teardowns = new StackQueue<Runnable>();
-
- /**
- * Adds the specified task to the tests setup.
- *
- * @param task The task to add to the tests setup.
- */
- public void chainSetupTask(Runnable task)
- {
- setups.offer(task);
- }
-
- /**
- * Adds the specified task to the tests tear down.
- *
- * @param task The task to add to the tests tear down.
- */
- public void chainTearDownTask(Runnable task)
- {
- teardowns.offer(task);
- }
-
- /**
- * Runs the set up tasks in the order that they way chained.
- */
- public void runSetupTasks()
- {
- while (!setups.isEmpty())
- {
- setups.remove().run();
- }
- }
-
- /**
- * Runs the tear down tasks in the reverse of the order in which they were chained.
- */
- public void runTearDownTasks()
- {
- while (!teardowns.isEmpty())
- {
- teardowns.remove().run();
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import org.apache.qpid.junit.extensions.util.StackQueue;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * SetupTaskHandler implements a task stack. It can be used, by delegation, as a base implementation for tests that want
+ * to have configurable setup/teardown task stacks. Typically it is up to the test implementation to decide whether the
+ * stack is executed in the setup/teardown methods or in the threadSetup/threadTeaddown methods.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Handle injection of set up tasks.
+ * <tr><td> Handle injection of tear down tasks.
+ * <tr><td> Run set up tasks in chain order.
+ * <tr><td> Run tear down tasks in reverse chain order.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class SetupTaskHandler implements SetupTaskAware
+{
+ /** Holds the set up tasks. */
+ Queue<Runnable> setups = new LinkedList<Runnable>();
+
+ /** Holds the tear down tasks. */
+ Queue<Runnable> teardowns = new StackQueue<Runnable>();
+
+ /**
+ * Adds the specified task to the tests setup.
+ *
+ * @param task The task to add to the tests setup.
+ */
+ public void chainSetupTask(Runnable task)
+ {
+ setups.offer(task);
+ }
+
+ /**
+ * Adds the specified task to the tests tear down.
+ *
+ * @param task The task to add to the tests tear down.
+ */
+ public void chainTearDownTask(Runnable task)
+ {
+ teardowns.offer(task);
+ }
+
+ /**
+ * Runs the set up tasks in the order that they way chained.
+ */
+ public void runSetupTasks()
+ {
+ while (!setups.isEmpty())
+ {
+ setups.remove().run();
+ }
+ }
+
+ /**
+ * Runs the tear down tasks in the reverse of the order in which they were chained.
+ */
+ public void runTearDownTasks()
+ {
+ while (!teardowns.isEmpty())
+ {
+ teardowns.remove().run();
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java
index 344d7abf82..dc6aa3c291 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/ShutdownHookable.java
@@ -1,42 +1,42 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-/**
- * Defines an interface that classes which supply shutdown hooks implement. Code that creates these classes can check
- * if they supply a shutdown hook and register these hooks when the obejct are created.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Supply a shutdown hook.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface ShutdownHookable
-{
- /**
- * Supplies the shutdown hook.
- *
- * @return The shut down hook.
- */
- public Thread getShutdownHook();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * Defines an interface that classes which supply shutdown hooks implement. Code that creates these classes can check
+ * if they supply a shutdown hook and register these hooks when the obejct are created.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Supply a shutdown hook.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface ShutdownHookable
+{
+ /**
+ * Supplies the shutdown hook.
+ *
+ * @return The shut down hook.
+ */
+ public Thread getShutdownHook();
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java
index f7e350b1c7..2dc4c0e272 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/SleepThrottle.java
@@ -1,81 +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.junit.extensions;
-
-/**
- * SleepThrottle is a Throttle implementation that generates short pauses using the thread sleep methods. As the pauses
- * get shorter, this technique gets more innacurate. In practice, around 100 Hz is the cap rate for accuracy.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept throttling rate in operations per second.
- * <tr><td> Inject short pauses to fill out processing cycles to a specified rate.
- * <tr><td> Check against a throttle speed without waiting.
- * </table>
- *
- * @author Rupert Smith
- */
-public class SleepThrottle extends BaseThrottle implements Throttle
-{
- /** Holds the time of the last call to the throttle method in nano seconds. */
- private long lastTimeNanos;
-
- /**
- * This method can only be called at the rate set by the {@link #setRate} method, if it is called faster than this
- * it will inject short pauses to restrict the call rate to that rate.
- */
- public void throttle()
- {
- // Get the current time in nanos.
- long currentTimeNanos = System.nanoTime();
-
- // Don't introduce any pause on the first call.
- if (!firstCall)
- {
- // Check if there is any time left in the cycle since the last call to this method and introduce a short pause
- // to fill that time if there is.
- long remainingTimeNanos = cycleTimeNanos - (currentTimeNanos - lastTimeNanos);
-
- if (remainingTimeNanos > 0)
- {
- long milliPause = remainingTimeNanos / 1000000;
- int nanoPause = (int) (remainingTimeNanos % 1000000);
-
- try
- {
- Thread.sleep(milliPause, nanoPause);
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted thread, in-case the caller is checking for it.
- Thread.currentThread().interrupt();
- }
- }
- }
- else
- {
- firstCall = false;
- }
-
- // Update the last time stamp.
- lastTimeNanos = System.nanoTime();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * SleepThrottle is a Throttle implementation that generates short pauses using the thread sleep methods. As the pauses
+ * get shorter, this technique gets more innacurate. In practice, around 100 Hz is the cap rate for accuracy.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept throttling rate in operations per second.
+ * <tr><td> Inject short pauses to fill out processing cycles to a specified rate.
+ * <tr><td> Check against a throttle speed without waiting.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class SleepThrottle extends BaseThrottle implements Throttle
+{
+ /** Holds the time of the last call to the throttle method in nano seconds. */
+ private long lastTimeNanos;
+
+ /**
+ * This method can only be called at the rate set by the {@link #setRate} method, if it is called faster than this
+ * it will inject short pauses to restrict the call rate to that rate.
+ */
+ public void throttle()
+ {
+ // Get the current time in nanos.
+ long currentTimeNanos = System.nanoTime();
+
+ // Don't introduce any pause on the first call.
+ if (!firstCall)
+ {
+ // Check if there is any time left in the cycle since the last call to this method and introduce a short pause
+ // to fill that time if there is.
+ long remainingTimeNanos = cycleTimeNanos - (currentTimeNanos - lastTimeNanos);
+
+ if (remainingTimeNanos > 0)
+ {
+ long milliPause = remainingTimeNanos / 1000000;
+ int nanoPause = (int) (remainingTimeNanos % 1000000);
+
+ try
+ {
+ Thread.sleep(milliPause, nanoPause);
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted thread, in-case the caller is checking for it.
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ else
+ {
+ firstCall = false;
+ }
+
+ // Update the last time stamp.
+ lastTimeNanos = System.nanoTime();
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java
index c9bcf3eb66..ae497c671b 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestResult.java
@@ -1,625 +1,625 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.listeners.TKTestListener;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Properties;
-
-/**
- * TKTestResult extends TestResult in order to calculate test timings, to pass the variable integer parameter for
- * parameterized test cases to those test cases and to introduce an optional delay before test starts. Interested
- * {@link TKTestListener}s may be attached to this and will be informed of all relevant test statistics.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Calculate test timings.
- * <tr><td> Inform timing listeners of timings.
- * <tr><td> Inform memory listeners of memory readings.
- * <tr><td> Inform parameters listeners of parameters.
- * <tr><td> Pass the integer parameter to parameterized test cases.
- * <tr><td> Provide verbose test information on test start and end.
- * </table>
- *
- * @todo Move the verbose test information on test start/end into a test listener instead. It confuses the intention
- * of this class. Could also move the delay into a listener but that seems less appropriate as it would be a
- * side-effecting listener. Delay and timing calculation are fundamental enough to this class.
- *
- * @todo The need for this class to act as a place-holder for the integer parameter for parameterized test cases is
- * because this behaviour has been factored out into a test decorator class, see {@link AsymptoticTestDecorator}.
- * The {@link AsymptoticTestDecorator#run} method takes a TestResult as an argument and cannot easily get to the
- * {@link AsymptoticTestCase} class other than through this class. The option of using this class as a place hold
- * for this value was chosen. Alternatively this class could provide a method for decorators to access the
- * underlying test case through and then leave the setting of this parameter to the decorator which is a more
- * natural home for this behaviour. It would also provide a more general framework for decorators.
- *
- * @todo The memory usage may need to be moved in closer to the test method invocation so that as little code as possible
- * exists between it and the test or the results may be obscured. In fact it certainly does as the teardown method
- * is getting called first. Wouldn't be a bad idea to move the timing code in closer too.
- *
- * @todo Get rid of the delay logic. Will be replaced by throttle control.
- *
- * @author Rupert Smith
- */
-public class TKTestResult extends TestResult
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(TKTestResult.class);
-
- /** The delay between two tests. */
- private int delay = 0;
-
- /**
- * This flag indicates that the #completeTest method of the timing controller has been called. Once this has
- * been called once, the end test event for the whole test method should be ignored because tests have taken
- * charge of outputing their own timings.
- */
- private boolean completeTestUsed = false;
-
- /**
- * Thread locals to hold test start time for non-instrumented tests. (Instrumented tests hold their own
- * measurement data).
- */
- // private Hashtable threadStartTimeMap = new Hashtable();
- private ThreadLocal<ThreadLocalSettings> threadLocals = new ThreadLocal<ThreadLocalSettings>();
-
- /** Used to hold the current integer parameter to pass to parameterized tests. This defaults to 1. */
- private int n = 1;
-
- /** The timing listeners. */
- private Collection<TKTestListener> tkListeners;
-
- /** The test case name. */
- private String testCaseName;
-
- /** Used to hold the current concurrency level, set by the {@link ScaledTestDecorator}. */
- private int concurrencyLevel = 1;
-
- /** Flag used to indicate that this test result should attempt to complete its current tests as soon as possible. */
- private boolean shutdownNow = false;
-
- /** Holds the parametes that the test is run with. */
- private Properties testParameters;
-
- /**
- * Creates a new TKTestResult object.
- *
- * @param delay A delay in milliseconds to introduce before every test start.
- * @param testCaseName The name of the test case that this is the TestResult object for.
- */
- public TKTestResult(int delay, String testCaseName)
- {
- super();
-
- /*log.debug("public TKTestResult(PrintStream writer, int " + delay + ", boolean " + verbose + ", String "
- + testCaseName + "): called");*/
-
- // Keep all the parameters that this is created with.
- this.delay = delay;
- this.testCaseName = testCaseName;
- }
-
- /**
- * Callback method use to inform this test result that a test will be started. Waits for the configured delay time
- * if one has been set, starts the timer, then delegates to the super class implementation.
- *
- * @param test The test to be started.
- */
- public void startTest(Test test)
- {
- // log.debug("public void startTest(Test test): called");
-
- // If a delay time has been specified then wait for that length of time.
- if (this.delay > 0)
- {
- try
- {
- Thread.sleep(delay);
- }
- catch (InterruptedException e)
- {
- // Ignore, but restore the interrupted flag.
- Thread.currentThread().interrupt();
- }
- }
-
- // Create the thread local settings for the test.
- ThreadLocalSettings threadLocalSettings = new ThreadLocalSettings();
- threadLocals.set(threadLocalSettings);
-
- // Record the test start time against this thread for calculating the test timing. (Consider using ThreadLocal
- // instead?)
- Long startTime = System.nanoTime();
- threadLocalSettings.startTime = startTime;
- // log.debug("startTime = " + startTime);
-
- // Check if the test is timing controller aware, in which case set up a new timing controller and hold it
- // in the thread local settings.
- if (test instanceof TimingControllerAware)
- {
- TimingControllerAware controllerAware = (TimingControllerAware) test;
- TimingControllerImpl controller =
- new TimingControllerImpl(this, test, startTime, Thread.currentThread().getId());
- controllerAware.setTimingController(controller);
-
- threadLocalSettings.timingController = controller;
- }
-
- // Delegate to the super method to notify test event listeners.
- super.startTest(test);
- }
-
- /**
- * Callback method use to inform this result that a test was completed. This calculates how long the test took
- * to run, then delegates to the super class implementation.
- *
- * @param test The test that has ended.
- */
- public void endTest(Test test)
- {
- // log.debug("public void endTest(Test test): called");
-
- long runTime = 0;
-
- // Recover the thread local settings.
- ThreadLocalSettings threadLocalSettings = threadLocals.get();
-
- // Check if the test is an instrumented test and get the timing information from the instrumentation as this
- // will be more accurate.
- if (test instanceof InstrumentedTest)
- {
- InstrumentedTest iTest = (InstrumentedTest) test;
-
- // Calculate the test run time.
- runTime = iTest.getTestTime();
- // log.debug("runTime = " + runTime);
-
- // Calculate the test memory usage.
- long startMem = iTest.getTestStartMemory();
- long endMem = iTest.getTestEndMemory();
-
- // log.debug("startMem = " + startMem);
- // log.debug("endMem = " + endMem);
-
- // Inform any memory listeners of the test memory.
- if (tkListeners != null)
- {
- for (TKTestListener memoryListener : tkListeners)
- {
- memoryListener.memoryUsed(test, startMem, endMem, null);
- }
- }
- }
- else
- {
- // Calculate the test run time.
- long endTime = System.nanoTime();
- Long startTime = threadLocalSettings.startTime;
- runTime = endTime - startTime;
- // log.debug("runTime = " + runTime);
-
- threadLocals.remove();
- }
-
- // Output end test stats. This is only done when the tests have not used the timing controller to output
- // mutiple timings.
- if (!completeTestUsed)
- {
- // Check if the test is an asymptotic test case and get its int parameter if so.
- if (test instanceof AsymptoticTestCase)
- {
- AsymptoticTestCase pTest = (AsymptoticTestCase) test;
-
- // Set the parameter.
- int paramValue = pTest.getN();
-
- // Inform any parameter listeners of the test parameter.
- if (tkListeners != null)
- {
- for (TKTestListener parameterListener : tkListeners)
- {
- parameterListener.parameterValue(test, paramValue, null);
- }
- }
- }
-
- // Inform any timing listeners of the test timing and concurrency level.
- if (tkListeners != null)
- {
- for (TKTestListener tkListener : tkListeners)
- {
- TKTestListener next = tkListener;
-
- next.timing(test, runTime, null);
- next.concurrencyLevel(test, concurrencyLevel, null);
- }
- }
-
- // Call the super method to notify test event listeners of the end event.
- super.endTest(test);
- }
- }
-
- /**
- * Gets the integer parameter to pass to parameterized test cases.
- *
- * @return The value of the integer parameter.
- */
- public int getN()
- {
- return n;
- }
-
- /**
- * Sets the integer parameter to pass to parameterized test cases.
- *
- * @param n The new value of the integer parameter.
- */
- public void setN(int n)
- {
- // log.debug("public void setN(int " + n + "): called");
-
- this.n = n;
- }
-
- /**
- * Adds a timing listener to pass all timing events to.
- *
- * @param listener The timing listener to register.
- */
- public void addTKTestListener(TKTestListener listener)
- {
- // Create the collection to hold the timing listeners if it does not already exist.
- if (tkListeners == null)
- {
- tkListeners = new ArrayList<TKTestListener>();
- }
-
- // Keep the new timing listener.
- tkListeners.add(listener);
- }
-
- /**
- * Called by the test runner to notify this that a new test batch is being begun. This method forwards this
- * notification to all batch listeners.
- */
- public void notifyStartBatch()
- {
- if (tkListeners != null)
- {
- for (TKTestListener batchListener : tkListeners)
- {
- batchListener.startBatch();
- }
- }
- }
-
- /**
- * Called by the test runner to notify this that the current test batch has been ended. This method forwards this
- * notification to all batch listener.
- */
- public void notifyEndBatch()
- {
- // log.debug("public void notifyEndBatch(): called");
-
- if (tkListeners != null)
- {
- for (TKTestListener batchListener : tkListeners)
- {
- batchListener.endBatch(testParameters);
- }
- }
- }
-
- /**
- * Called by the test runner to notify this of the properties that the test is using.
- *
- * @param properties The tests set/read properties.
- */
- public void notifyTestProperties(Properties properties)
- {
- // log.debug("public void notifyTestProperties(Properties properties): called");
-
- this.testParameters = properties;
-
- /*
- if (tkListeners != null)
- {
- for (TKTestListener batchListener : tkListeners)
- {
- batchListener.properties(properties);
- }
- }
- */
- }
-
- /**
- * Intercepts the execution of a test case to pass the variable integer parameter to a test if it is a parameterized
- * test case.
- *
- * @param test The test to run.
- */
- protected void run(final TestCase test)
- {
- // log.debug("protected void run(final TestCase test): called");
-
- // Check if the test case is a parameterized test and set its integer parameter if so.
- if (test instanceof AsymptoticTestCase)
- {
- AsymptoticTestCase pTest = (AsymptoticTestCase) test;
-
- // Set up the integer parameter.
- pTest.setN(n);
- }
-
- // Delegate to the super method to run the test.
- super.run(test);
- }
-
- /**
- * Helper method that generats a String of verbose information about a test. This includes the thread name, test
- * class name and test method name.
- *
- * @param test The test to generate the info string for.
- *
- * @return Returns a string with the thread name, test class name and test method name.
- */
- protected String getTestInfo(Test test)
- {
- // log.debug("protected String getTestInfo(Test test): called");
-
- return "[" + Thread.currentThread().getName() + "@" + test.getClass().getName() + "."
- + ((test instanceof TestCase) ? ((TestCase) test).getName() : "") + "]";
- }
-
- /**
- * Sets the concurrency level to pass into the test result.
- *
- * @param concurrencyLevel The concurrency level the tests are running out.
- */
- public void setConcurrencyLevel(int concurrencyLevel)
- {
- this.concurrencyLevel = concurrencyLevel;
- }
-
- /**
- * Tells this test result that it should stop running tests. Once this method has been called this test result
- * will not start any new tests, and any tests that use the timing controller will be passed interrupted exceptions,
- * to indicate that they should end immediately. Usually the caller of this method will introduce a short wait
- * to allow an opporunity for running tests to complete, before forcing the shutdown of the JVM.
- */
- public void shutdownNow()
- {
- log.debug("public void shutdownNow(): called on " + this);
-
- shutdownNow = true;
- }
-
- /**
- * Prints a string summary of this class, mainly for debugging purposes.
- *
- * @return A string summary of this class, mainly for debugging purposes.
- */
- public String toString()
- {
- return "TKTestResult@" + Integer.toString(hashCode(), 16) + ": [ testCaseName = " + testCaseName + ", n = " + n
- + ", tkListeners = " + tkListeners + " ]";
- }
-
- /**
- * Holds things that need to be kept on a per thread basis for each test invocation, such as the test start
- * time and its timing controller.
- */
- private static class ThreadLocalSettings
- {
- /** Holds the test start time. */
- Long startTime;
-
- /** Holds the test threads timing controller. */
- TimingController timingController;
- }
-
- /**
- * Provides an implementation of the {@link TimingController} interface that timing aware tests can use to call
- * back to reset timers, and register additional test timings.
- */
- private static class TimingControllerImpl implements TimingController
- {
- /** Holds an explicit reference to the test TKTestResult that created this. */
- TKTestResult testResult;
-
- /** Holds a reference to the test that this is the timing controller for. */
- Test test;
-
- /** Holds the start time for this timing controller. This gets reset to now on each completed test. */
- long startTime;
-
- /**
- * Holds the thread id of the thread that started the test, so that this controller may be called from other
- * threads but still identify itself correctly to {@link TKTestListener}s as being associated with the
- * thread that called the test method.
- */
- long threadId;
-
- /**
- * Creates a timing controller on a specified TKTestResult and a test.
- *
- * @param testResult The TKTestResult that this controller interacts with.
- * @param test The test that this is the timing controller for.
- * @param startTime The test start time in nanoseconds.
- * @param threadId The thread id of the thread that is calling the test method.
- */
- public TimingControllerImpl(TKTestResult testResult, Test test, long startTime, long threadId)
- {
- this.testResult = testResult;
- this.test = test;
- this.startTime = startTime;
- this.threadId = threadId;
- }
-
- /**
- * Gets the timing controller associated with the current test thread. Tests that use timing controller should
- * always get the timing controller from this method in the same thread that called the setUp, tearDown or test
- * method. The controller returned by this method may be called from any thread because it remembers the thread
- * id of the original test thread.
- *
- * @return The timing controller associated with the current test thread.
- */
- public TimingController getControllerForCurrentThread()
- {
- // Recover the thread local settings and extract the timing controller from them.
- ThreadLocalSettings threadLocalSettings = testResult.threadLocals.get();
-
- return threadLocalSettings.timingController;
- }
-
- /**
- * Not implemented yet.
- *
- * @return Nothing.
- */
- public long suspend()
- {
- throw new RuntimeException("Method not implemented.");
- }
-
- /**
- * Not implemented yet.
- *
- * @return Nothing.
- */
- public long resume()
- {
- throw new RuntimeException("Method not implemented.");
- }
-
- /**
- * Resets the timer start time to now.
- *
- * @return The new value of the start time.
- */
- public long restart()
- {
- startTime = System.nanoTime();
-
- return startTime;
- }
-
- /**
- * Register an additional pass/fail for the current test. The test result is assumed to apply to a test of
- * 'size' parmeter 1. Use the {@link #completeTest(boolean, int)} method to register timings with parameters.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed) throws InterruptedException
- {
- completeTest(testPassed, 1);
- }
-
- /**
- * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
- * 'size' parmeter.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- * @param param The test parameter size for parameterized tests.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed, int param) throws InterruptedException
- {
- /*log.debug("public long completeTest(boolean testPassed = " + testPassed + ", int param = " + param
- + "): called");*/
-
- // Calculate the test run time.
- long endTime = System.nanoTime();
- long runTime = endTime - startTime;
- // log.debug("runTime = " + runTime);
-
- // Reset the test start time to now, to reset the timer for the next result.
- startTime = endTime;
-
- completeTest(testPassed, param, runTime);
- }
-
- /**
- * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
- * 'size' parmeter and allows the caller to sepecify the timing to log.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- * @param param The test parameter size for parameterized tests.
- * @param timeNanos The time in nano-seconds to log the test result with.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed, int param, long timeNanos) throws InterruptedException
- {
- log.debug("public void completeTest(boolean testPassed, int param, long timeNanos): called");
- log.debug("testResult = " + testResult);
-
- // Tell the test result that completeTest has been used, so to not register end test events for the whole
- // test method.
- testResult.completeTestUsed = true;
-
- // Inform any timing listeners of the test timings and parameters and send an end test notification using
- // the thread id of the thread that started the test.
- if (testResult.tkListeners != null)
- {
- for (TKTestListener listener : testResult.tkListeners)
- {
- listener.reset(test, threadId);
- listener.timing(test, timeNanos, threadId);
- listener.parameterValue(test, param, threadId);
- listener.concurrencyLevel(test, testResult.concurrencyLevel, threadId);
-
- if (!testPassed)
- {
- listener.addFailure(test, null, threadId);
- }
-
- listener.endTest(test, threadId);
- }
- }
-
- // log.debug("testResult.shutdownNow = " + testResult.shutdownNow);
-
- // Check if the test runner has been asked to shutdown and raise an interuppted exception if so.
- if (testResult.shutdownNow)
- {
- // log.debug("The shutdown flag is set.");
-
- throw new InterruptedException("Attempting clean shutdown by suspending current test.");
- }
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.listeners.TKTestListener;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+
+/**
+ * TKTestResult extends TestResult in order to calculate test timings, to pass the variable integer parameter for
+ * parameterized test cases to those test cases and to introduce an optional delay before test starts. Interested
+ * {@link TKTestListener}s may be attached to this and will be informed of all relevant test statistics.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Calculate test timings.
+ * <tr><td> Inform timing listeners of timings.
+ * <tr><td> Inform memory listeners of memory readings.
+ * <tr><td> Inform parameters listeners of parameters.
+ * <tr><td> Pass the integer parameter to parameterized test cases.
+ * <tr><td> Provide verbose test information on test start and end.
+ * </table>
+ *
+ * @todo Move the verbose test information on test start/end into a test listener instead. It confuses the intention
+ * of this class. Could also move the delay into a listener but that seems less appropriate as it would be a
+ * side-effecting listener. Delay and timing calculation are fundamental enough to this class.
+ *
+ * @todo The need for this class to act as a place-holder for the integer parameter for parameterized test cases is
+ * because this behaviour has been factored out into a test decorator class, see {@link AsymptoticTestDecorator}.
+ * The {@link AsymptoticTestDecorator#run} method takes a TestResult as an argument and cannot easily get to the
+ * {@link AsymptoticTestCase} class other than through this class. The option of using this class as a place hold
+ * for this value was chosen. Alternatively this class could provide a method for decorators to access the
+ * underlying test case through and then leave the setting of this parameter to the decorator which is a more
+ * natural home for this behaviour. It would also provide a more general framework for decorators.
+ *
+ * @todo The memory usage may need to be moved in closer to the test method invocation so that as little code as possible
+ * exists between it and the test or the results may be obscured. In fact it certainly does as the teardown method
+ * is getting called first. Wouldn't be a bad idea to move the timing code in closer too.
+ *
+ * @todo Get rid of the delay logic. Will be replaced by throttle control.
+ *
+ * @author Rupert Smith
+ */
+public class TKTestResult extends TestResult
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(TKTestResult.class);
+
+ /** The delay between two tests. */
+ private int delay = 0;
+
+ /**
+ * This flag indicates that the #completeTest method of the timing controller has been called. Once this has
+ * been called once, the end test event for the whole test method should be ignored because tests have taken
+ * charge of outputing their own timings.
+ */
+ private boolean completeTestUsed = false;
+
+ /**
+ * Thread locals to hold test start time for non-instrumented tests. (Instrumented tests hold their own
+ * measurement data).
+ */
+ // private Hashtable threadStartTimeMap = new Hashtable();
+ private ThreadLocal<ThreadLocalSettings> threadLocals = new ThreadLocal<ThreadLocalSettings>();
+
+ /** Used to hold the current integer parameter to pass to parameterized tests. This defaults to 1. */
+ private int n = 1;
+
+ /** The timing listeners. */
+ private Collection<TKTestListener> tkListeners;
+
+ /** The test case name. */
+ private String testCaseName;
+
+ /** Used to hold the current concurrency level, set by the {@link ScaledTestDecorator}. */
+ private int concurrencyLevel = 1;
+
+ /** Flag used to indicate that this test result should attempt to complete its current tests as soon as possible. */
+ private boolean shutdownNow = false;
+
+ /** Holds the parametes that the test is run with. */
+ private Properties testParameters;
+
+ /**
+ * Creates a new TKTestResult object.
+ *
+ * @param delay A delay in milliseconds to introduce before every test start.
+ * @param testCaseName The name of the test case that this is the TestResult object for.
+ */
+ public TKTestResult(int delay, String testCaseName)
+ {
+ super();
+
+ /*log.debug("public TKTestResult(PrintStream writer, int " + delay + ", boolean " + verbose + ", String "
+ + testCaseName + "): called");*/
+
+ // Keep all the parameters that this is created with.
+ this.delay = delay;
+ this.testCaseName = testCaseName;
+ }
+
+ /**
+ * Callback method use to inform this test result that a test will be started. Waits for the configured delay time
+ * if one has been set, starts the timer, then delegates to the super class implementation.
+ *
+ * @param test The test to be started.
+ */
+ public void startTest(Test test)
+ {
+ // log.debug("public void startTest(Test test): called");
+
+ // If a delay time has been specified then wait for that length of time.
+ if (this.delay > 0)
+ {
+ try
+ {
+ Thread.sleep(delay);
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore, but restore the interrupted flag.
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ // Create the thread local settings for the test.
+ ThreadLocalSettings threadLocalSettings = new ThreadLocalSettings();
+ threadLocals.set(threadLocalSettings);
+
+ // Record the test start time against this thread for calculating the test timing. (Consider using ThreadLocal
+ // instead?)
+ Long startTime = System.nanoTime();
+ threadLocalSettings.startTime = startTime;
+ // log.debug("startTime = " + startTime);
+
+ // Check if the test is timing controller aware, in which case set up a new timing controller and hold it
+ // in the thread local settings.
+ if (test instanceof TimingControllerAware)
+ {
+ TimingControllerAware controllerAware = (TimingControllerAware) test;
+ TimingControllerImpl controller =
+ new TimingControllerImpl(this, test, startTime, Thread.currentThread().getId());
+ controllerAware.setTimingController(controller);
+
+ threadLocalSettings.timingController = controller;
+ }
+
+ // Delegate to the super method to notify test event listeners.
+ super.startTest(test);
+ }
+
+ /**
+ * Callback method use to inform this result that a test was completed. This calculates how long the test took
+ * to run, then delegates to the super class implementation.
+ *
+ * @param test The test that has ended.
+ */
+ public void endTest(Test test)
+ {
+ // log.debug("public void endTest(Test test): called");
+
+ long runTime = 0;
+
+ // Recover the thread local settings.
+ ThreadLocalSettings threadLocalSettings = threadLocals.get();
+
+ // Check if the test is an instrumented test and get the timing information from the instrumentation as this
+ // will be more accurate.
+ if (test instanceof InstrumentedTest)
+ {
+ InstrumentedTest iTest = (InstrumentedTest) test;
+
+ // Calculate the test run time.
+ runTime = iTest.getTestTime();
+ // log.debug("runTime = " + runTime);
+
+ // Calculate the test memory usage.
+ long startMem = iTest.getTestStartMemory();
+ long endMem = iTest.getTestEndMemory();
+
+ // log.debug("startMem = " + startMem);
+ // log.debug("endMem = " + endMem);
+
+ // Inform any memory listeners of the test memory.
+ if (tkListeners != null)
+ {
+ for (TKTestListener memoryListener : tkListeners)
+ {
+ memoryListener.memoryUsed(test, startMem, endMem, null);
+ }
+ }
+ }
+ else
+ {
+ // Calculate the test run time.
+ long endTime = System.nanoTime();
+ Long startTime = threadLocalSettings.startTime;
+ runTime = endTime - startTime;
+ // log.debug("runTime = " + runTime);
+
+ threadLocals.remove();
+ }
+
+ // Output end test stats. This is only done when the tests have not used the timing controller to output
+ // mutiple timings.
+ if (!completeTestUsed)
+ {
+ // Check if the test is an asymptotic test case and get its int parameter if so.
+ if (test instanceof AsymptoticTestCase)
+ {
+ AsymptoticTestCase pTest = (AsymptoticTestCase) test;
+
+ // Set the parameter.
+ int paramValue = pTest.getN();
+
+ // Inform any parameter listeners of the test parameter.
+ if (tkListeners != null)
+ {
+ for (TKTestListener parameterListener : tkListeners)
+ {
+ parameterListener.parameterValue(test, paramValue, null);
+ }
+ }
+ }
+
+ // Inform any timing listeners of the test timing and concurrency level.
+ if (tkListeners != null)
+ {
+ for (TKTestListener tkListener : tkListeners)
+ {
+ TKTestListener next = tkListener;
+
+ next.timing(test, runTime, null);
+ next.concurrencyLevel(test, concurrencyLevel, null);
+ }
+ }
+
+ // Call the super method to notify test event listeners of the end event.
+ super.endTest(test);
+ }
+ }
+
+ /**
+ * Gets the integer parameter to pass to parameterized test cases.
+ *
+ * @return The value of the integer parameter.
+ */
+ public int getN()
+ {
+ return n;
+ }
+
+ /**
+ * Sets the integer parameter to pass to parameterized test cases.
+ *
+ * @param n The new value of the integer parameter.
+ */
+ public void setN(int n)
+ {
+ // log.debug("public void setN(int " + n + "): called");
+
+ this.n = n;
+ }
+
+ /**
+ * Adds a timing listener to pass all timing events to.
+ *
+ * @param listener The timing listener to register.
+ */
+ public void addTKTestListener(TKTestListener listener)
+ {
+ // Create the collection to hold the timing listeners if it does not already exist.
+ if (tkListeners == null)
+ {
+ tkListeners = new ArrayList<TKTestListener>();
+ }
+
+ // Keep the new timing listener.
+ tkListeners.add(listener);
+ }
+
+ /**
+ * Called by the test runner to notify this that a new test batch is being begun. This method forwards this
+ * notification to all batch listeners.
+ */
+ public void notifyStartBatch()
+ {
+ if (tkListeners != null)
+ {
+ for (TKTestListener batchListener : tkListeners)
+ {
+ batchListener.startBatch();
+ }
+ }
+ }
+
+ /**
+ * Called by the test runner to notify this that the current test batch has been ended. This method forwards this
+ * notification to all batch listener.
+ */
+ public void notifyEndBatch()
+ {
+ // log.debug("public void notifyEndBatch(): called");
+
+ if (tkListeners != null)
+ {
+ for (TKTestListener batchListener : tkListeners)
+ {
+ batchListener.endBatch(testParameters);
+ }
+ }
+ }
+
+ /**
+ * Called by the test runner to notify this of the properties that the test is using.
+ *
+ * @param properties The tests set/read properties.
+ */
+ public void notifyTestProperties(Properties properties)
+ {
+ // log.debug("public void notifyTestProperties(Properties properties): called");
+
+ this.testParameters = properties;
+
+ /*
+ if (tkListeners != null)
+ {
+ for (TKTestListener batchListener : tkListeners)
+ {
+ batchListener.properties(properties);
+ }
+ }
+ */
+ }
+
+ /**
+ * Intercepts the execution of a test case to pass the variable integer parameter to a test if it is a parameterized
+ * test case.
+ *
+ * @param test The test to run.
+ */
+ protected void run(final TestCase test)
+ {
+ // log.debug("protected void run(final TestCase test): called");
+
+ // Check if the test case is a parameterized test and set its integer parameter if so.
+ if (test instanceof AsymptoticTestCase)
+ {
+ AsymptoticTestCase pTest = (AsymptoticTestCase) test;
+
+ // Set up the integer parameter.
+ pTest.setN(n);
+ }
+
+ // Delegate to the super method to run the test.
+ super.run(test);
+ }
+
+ /**
+ * Helper method that generats a String of verbose information about a test. This includes the thread name, test
+ * class name and test method name.
+ *
+ * @param test The test to generate the info string for.
+ *
+ * @return Returns a string with the thread name, test class name and test method name.
+ */
+ protected String getTestInfo(Test test)
+ {
+ // log.debug("protected String getTestInfo(Test test): called");
+
+ return "[" + Thread.currentThread().getName() + "@" + test.getClass().getName() + "."
+ + ((test instanceof TestCase) ? ((TestCase) test).getName() : "") + "]";
+ }
+
+ /**
+ * Sets the concurrency level to pass into the test result.
+ *
+ * @param concurrencyLevel The concurrency level the tests are running out.
+ */
+ public void setConcurrencyLevel(int concurrencyLevel)
+ {
+ this.concurrencyLevel = concurrencyLevel;
+ }
+
+ /**
+ * Tells this test result that it should stop running tests. Once this method has been called this test result
+ * will not start any new tests, and any tests that use the timing controller will be passed interrupted exceptions,
+ * to indicate that they should end immediately. Usually the caller of this method will introduce a short wait
+ * to allow an opporunity for running tests to complete, before forcing the shutdown of the JVM.
+ */
+ public void shutdownNow()
+ {
+ log.debug("public void shutdownNow(): called on " + this);
+
+ shutdownNow = true;
+ }
+
+ /**
+ * Prints a string summary of this class, mainly for debugging purposes.
+ *
+ * @return A string summary of this class, mainly for debugging purposes.
+ */
+ public String toString()
+ {
+ return "TKTestResult@" + Integer.toString(hashCode(), 16) + ": [ testCaseName = " + testCaseName + ", n = " + n
+ + ", tkListeners = " + tkListeners + " ]";
+ }
+
+ /**
+ * Holds things that need to be kept on a per thread basis for each test invocation, such as the test start
+ * time and its timing controller.
+ */
+ private static class ThreadLocalSettings
+ {
+ /** Holds the test start time. */
+ Long startTime;
+
+ /** Holds the test threads timing controller. */
+ TimingController timingController;
+ }
+
+ /**
+ * Provides an implementation of the {@link TimingController} interface that timing aware tests can use to call
+ * back to reset timers, and register additional test timings.
+ */
+ private static class TimingControllerImpl implements TimingController
+ {
+ /** Holds an explicit reference to the test TKTestResult that created this. */
+ TKTestResult testResult;
+
+ /** Holds a reference to the test that this is the timing controller for. */
+ Test test;
+
+ /** Holds the start time for this timing controller. This gets reset to now on each completed test. */
+ long startTime;
+
+ /**
+ * Holds the thread id of the thread that started the test, so that this controller may be called from other
+ * threads but still identify itself correctly to {@link TKTestListener}s as being associated with the
+ * thread that called the test method.
+ */
+ long threadId;
+
+ /**
+ * Creates a timing controller on a specified TKTestResult and a test.
+ *
+ * @param testResult The TKTestResult that this controller interacts with.
+ * @param test The test that this is the timing controller for.
+ * @param startTime The test start time in nanoseconds.
+ * @param threadId The thread id of the thread that is calling the test method.
+ */
+ public TimingControllerImpl(TKTestResult testResult, Test test, long startTime, long threadId)
+ {
+ this.testResult = testResult;
+ this.test = test;
+ this.startTime = startTime;
+ this.threadId = threadId;
+ }
+
+ /**
+ * Gets the timing controller associated with the current test thread. Tests that use timing controller should
+ * always get the timing controller from this method in the same thread that called the setUp, tearDown or test
+ * method. The controller returned by this method may be called from any thread because it remembers the thread
+ * id of the original test thread.
+ *
+ * @return The timing controller associated with the current test thread.
+ */
+ public TimingController getControllerForCurrentThread()
+ {
+ // Recover the thread local settings and extract the timing controller from them.
+ ThreadLocalSettings threadLocalSettings = testResult.threadLocals.get();
+
+ return threadLocalSettings.timingController;
+ }
+
+ /**
+ * Not implemented yet.
+ *
+ * @return Nothing.
+ */
+ public long suspend()
+ {
+ throw new RuntimeException("Method not implemented.");
+ }
+
+ /**
+ * Not implemented yet.
+ *
+ * @return Nothing.
+ */
+ public long resume()
+ {
+ throw new RuntimeException("Method not implemented.");
+ }
+
+ /**
+ * Resets the timer start time to now.
+ *
+ * @return The new value of the start time.
+ */
+ public long restart()
+ {
+ startTime = System.nanoTime();
+
+ return startTime;
+ }
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is assumed to apply to a test of
+ * 'size' parmeter 1. Use the {@link #completeTest(boolean, int)} method to register timings with parameters.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed) throws InterruptedException
+ {
+ completeTest(testPassed, 1);
+ }
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
+ * 'size' parmeter.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ * @param param The test parameter size for parameterized tests.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed, int param) throws InterruptedException
+ {
+ /*log.debug("public long completeTest(boolean testPassed = " + testPassed + ", int param = " + param
+ + "): called");*/
+
+ // Calculate the test run time.
+ long endTime = System.nanoTime();
+ long runTime = endTime - startTime;
+ // log.debug("runTime = " + runTime);
+
+ // Reset the test start time to now, to reset the timer for the next result.
+ startTime = endTime;
+
+ completeTest(testPassed, param, runTime);
+ }
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
+ * 'size' parmeter and allows the caller to sepecify the timing to log.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ * @param param The test parameter size for parameterized tests.
+ * @param timeNanos The time in nano-seconds to log the test result with.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed, int param, long timeNanos) throws InterruptedException
+ {
+ log.debug("public void completeTest(boolean testPassed, int param, long timeNanos): called");
+ log.debug("testResult = " + testResult);
+
+ // Tell the test result that completeTest has been used, so to not register end test events for the whole
+ // test method.
+ testResult.completeTestUsed = true;
+
+ // Inform any timing listeners of the test timings and parameters and send an end test notification using
+ // the thread id of the thread that started the test.
+ if (testResult.tkListeners != null)
+ {
+ for (TKTestListener listener : testResult.tkListeners)
+ {
+ listener.reset(test, threadId);
+ listener.timing(test, timeNanos, threadId);
+ listener.parameterValue(test, param, threadId);
+ listener.concurrencyLevel(test, testResult.concurrencyLevel, threadId);
+
+ if (!testPassed)
+ {
+ listener.addFailure(test, null, threadId);
+ }
+
+ listener.endTest(test, threadId);
+ }
+ }
+
+ // log.debug("testResult.shutdownNow = " + testResult.shutdownNow);
+
+ // Check if the test runner has been asked to shutdown and raise an interuppted exception if so.
+ if (testResult.shutdownNow)
+ {
+ // log.debug("The shutdown flag is set.");
+
+ throw new InterruptedException("Attempting clean shutdown by suspending current test.");
+ }
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java
index 7955a2e2e9..671d33feed 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TKTestRunner.java
@@ -1,694 +1,694 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.listeners.CSVTestListener;
-import org.apache.qpid.junit.extensions.listeners.ConsoleTestListener;
-import org.apache.qpid.junit.extensions.listeners.XMLTestListener;
-import org.apache.qpid.junit.extensions.util.CommandLineParser;
-import org.apache.qpid.junit.extensions.util.MathUtils;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import java.io.*;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * TKTestRunner extends {@link junit.textui.TestRunner} with the ability to run tests multiple times, to execute a test
- * simultaneously using many threads, to put a delay between test runs and adds support for tests that take integer
- * parameters that can be 'stepped' through on multiple test runs. These features can be accessed by using this class
- * as an entry point and passing command line arguments to specify which features to use:
- *
- * <pre>
- * -w ms The number of milliseconds between invocations of test cases.
- * -c pattern The number of tests to run concurrently.
- * -r num The number of times to repeat each test.
- * -d duration The length of time to run the tests for.
- * -t name The name of the test case to execute.
- * -s pattern The size parameter to run tests with.
- * -o dir The name of the directory to output test timings to.
- * --csv Output test results in CSV format.
- * --xml Output test results in XML format.
- * </pre>
- *
- * <p/>This command line may also have trailing 'name=value' parameters added to it. All of these values are added
- * to the test context properties and passed to the test, which can access them by name.
- *
- * <p/>The pattern arguments are of the form [lowest(: ...)(: highest)](:sample=s)(:exp), where round brackets
- * enclose optional values. Using this pattern form it is possible to specify a single value, a range of values divided
- * into s samples, a range of values divided into s samples but distributed exponentially, or a fixed set of samples.
- *
- * <p/>The duration arguments are of the form (dD)(hH)(mM)(sS), where round brackets enclose optional values. At least
- * one of the optional values must be present.
- *
- * <p/>When specifying optional test parameters on the command line, in 'name=value' format, it is also possible to use
- * the format 'name=[value1:value2:value3:...]', to specify multiple values for a parameter. All permutations of all
- * parameters with multiple values will be created and tested. If the values are numerical, it is also possible to use
- * the sequence generation patterns instead of fully specifying all of the values.
- *
- * <p/>Here are some examples:
- *
- * <p/><table>
- * <tr><td><pre> -c [10:20:30:40:50] </pre><td> Runs the test with 10,20,...,50 threads.
- * <tr><td><pre> -s [1:100]:samples=10 </pre>
- * <td> Runs the test with ten different size parameters evenly spaced between 1 and 100.
- * <tr><td><pre> -s [1:1000000]:samples=10:exp </pre>
- * <td> Runs the test with ten different size parameters exponentially spaced between 1 and 1000000.
- * <tr><td><pre> -r 10 </pre><td> Runs each test ten times.
- * <tr><td><pre> -d 10H </pre><td> Runs the test repeatedly for 10 hours.
- * <tr><td><pre> -d 1M, -r 10 </pre>
- * <td> Runs the test repeatedly for 1 minute but only takes a timing sample every 10 test runs.
- * <tr><td><pre> -r 10, -c [1:5:10:50], -s [100:1000:10000] </pre>
- * <td> Runs 12 test cycles (4 concurrency samples * 3 size sample), with 10 repeats each. In total the test
- * will be run 199 times (3 + 15 + 30 + 150)
- * <tr><td><pre> cache=true </pre><td> Passes the 'cache' parameter with value 'true' to the test.
- * <tr><td><pre> cache=[true:false] </pre><td> Runs the test with the 'cache' parameter set to 'true' and 'false'.
- * <tr><td><pre> cacheSize=[1000:1000000],samples=4,exp </pre>
- * <td> Runs the test with the 'cache' parameter set to a series of exponentially increasing sizes.
- * </table>
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Create the test configuration specified by the command line parameters.
- * </table>
- *
- * @todo Verify that the output directory exists or can be created.
- *
- * @todo Verify that the specific named test case to execute exists.
- *
- * @todo Drop the delay parameter as it is being replaced by throttling.
- *
- * @todo Completely replace the test ui test runner, instead of having TKTestRunner inherit from it, its just not
- * good code to extend.
- *
- * @author Rupert Smith
- */
-public class TKTestRunner extends TestRunnerImprovedErrorHandling
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TKTestRunner.class);
-
- /** Used for displaying information on the console. */
- // private static final Logger console = Logger.getLogger("CONSOLE." + TKTestRunner.class.getName());
-
- /** Used for generating the timestamp when naming output files. */
- protected static final DateFormat TIME_STAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
-
- /** Number of times to rerun the test. */
- protected Integer repetitions = 1;
-
- /** The length of time to run the tests for. */
- protected Long duration;
-
- /** Number of threads running the tests. */
- protected int[] threads;
-
- /** Delay in ms to wait between two test cases. */
- protected int delay = 0;
-
- /** The parameter values to pass to parameterized tests. */
- protected int[] params;
-
- /** Name of the single test case to execute. */
- protected String testCaseName = null;
-
- /** Name of the test class. */
- protected String testClassName = null;
-
- /** Name of the test run. */
- protected String testRunName = null;
-
- /** Directory to output XML reports into, if specified. */
- protected String reportDir = null;
-
- /** Flag that indicates the CSV results listener should be used to output results. */
- protected boolean csvResults;
-
- /** Flag that indiciates the XML results listener should be used to output results. */
- protected boolean xmlResults;
-
- /**
- * Holds the name of the class of the test currently being run. Ideally passed into the {@link #createTestResult}
- * method, but as the signature is already fixed for this, the current value gets pushed here as a member variable.
- */
- protected String currentTestClassName;
-
- /** Holds the test results object, which is reponsible for instrumenting tests/threads to record results. */
- protected TKTestResult result;
-
- /** Holds a list of factories for instantiating optional user specified test decorators. */
- protected List<TestDecoratorFactory> decoratorFactories;
-
- /**
- * Constructs a TKTestRunner using System.out for all the output.
- *
- * @param repetitions The number of times to repeat the test, or test batch size.
- * @param duration The length of time to run the tests for. -1 means no duration has been set.
- * @param threads The concurrency levels to ramp up to.
- * @param delay A delay in milliseconds between test runs.
- * @param params The sets of 'size' parameters to pass to test.
- * @param testCaseName The name of the test case to run.
- * @param reportDir The directory to output the test results to.
- * @param runName The name of the test run; used to name the output file.
- * @param csvResults <tt>true</tt> if the CSV results listener should be attached.
- * @param xmlResults <tt>true</tt> if the XML results listener should be attached.
- * @param decoratorFactories List of factories for user specified decorators.
- */
- public TKTestRunner(Integer repetitions, Long duration, int[] threads, int delay, int[] params, String testCaseName,
- String reportDir, String runName, boolean csvResults, boolean xmlResults,
- List<TestDecoratorFactory> decoratorFactories)
- {
- super(new NullResultPrinter(System.out));
-
- log.debug("public TKTestRunner(): called");
-
- // Keep all the test parameters.
- this.repetitions = repetitions;
- this.duration = duration;
- this.threads = threads;
- this.delay = delay;
- this.params = params;
- this.testCaseName = testCaseName;
- this.reportDir = reportDir;
- this.testRunName = runName;
- this.csvResults = csvResults;
- this.xmlResults = xmlResults;
- this.decoratorFactories = decoratorFactories;
- }
-
- /**
- * The entry point for the toolkit test runner.
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- // Use the command line parser to evaluate the command line.
- CommandLineParser commandLine =
- new CommandLineParser(
- new String[][]
- {
- { "w", "The number of milliseconds between invocations of test cases.", "ms", "false" },
- { "c", "The number of tests to run concurrently.", "num", "false", MathUtils.SEQUENCE_REGEXP },
- { "r", "The number of times to repeat each test.", "num", "false" },
- { "d", "The length of time to run the tests for.", "duration", "false", MathUtils.DURATION_REGEXP },
- { "f", "The maximum rate to call the tests at.", "frequency", "false", "^([1-9][0-9]*)/([1-9][0-9]*)$" },
- { "s", "The size parameter to run tests with.", "size", "false", MathUtils.SEQUENCE_REGEXP },
- { "t", "The name of the test case to execute.", "name", "false" },
- { "o", "The name of the directory to output test timings to.", "dir", "false" },
- { "n", "A name for this test run, used to name the output file.", "name", "true" },
- {
- "X:decorators", "A list of additional test decorators to wrap the tests in.",
- "\"class.name[:class.name]*\"", "false"
- },
- { "1", "Test class.", "class", "true" },
- { "-csv", "Output test results in CSV format.", null, "false" },
- { "-xml", "Output test results in XML format.", null, "false" }
- });
-
- // Capture the command line arguments or display errors and correct usage and then exit.
- ParsedProperties options = null;
-
- try
- {
- options = new ParsedProperties(commandLine.parseCommandLine(args));
- }
- catch (IllegalArgumentException e)
- {
- System.out.println(commandLine.getErrors());
- System.out.println(commandLine.getUsage());
- System.exit(FAILURE_EXIT);
- }
-
- // Extract the command line options.
- Integer delay = options.getPropertyAsInteger("w");
- String threadsString = options.getProperty("c");
- Integer repetitions = options.getPropertyAsInteger("r");
- String durationString = options.getProperty("d");
- String paramsString = options.getProperty("s");
- String testCaseName = options.getProperty("t");
- String reportDir = options.getProperty("o");
- String testRunName = options.getProperty("n");
- String decorators = options.getProperty("X:decorators");
- String testClassName = options.getProperty("1");
- boolean csvResults = options.getPropertyAsBoolean("-csv");
- boolean xmlResults = options.getPropertyAsBoolean("-xml");
-
- int[] threads = (threadsString == null) ? null : MathUtils.parseSequence(threadsString);
- int[] params = (paramsString == null) ? null : MathUtils.parseSequence(paramsString);
- Long duration = (durationString == null) ? null : MathUtils.parseDuration(durationString);
-
- // The test run name defaults to the test class name unless a value was specified for it.
- testRunName = (testRunName == null) ? testClassName : testRunName;
-
- // Add all the command line options and trailing settings to test context properties. Tests may pick up
- // overridden values from there, and these values will be logged in the test results, for analysis and
- // to make tests repeatable.
- commandLine.addTrailingPairsToProperties(TestContextProperties.getInstance());
- commandLine.addOptionsToProperties(TestContextProperties.getInstance());
-
- // Create and start the test runner.
- try
- {
- // Create a list of test decorator factories for use specified decorators to be applied.
- List<TestDecoratorFactory> decoratorFactories = parseDecorators(decorators);
-
- TKTestRunner testRunner =
- new TKTestRunner(repetitions, duration, threads, (delay == null) ? 0 : delay, params, testCaseName,
- reportDir, testRunName, csvResults, xmlResults, decoratorFactories);
-
- TestResult testResult = testRunner.start(testClassName);
-
- if (!testResult.wasSuccessful())
- {
- System.exit(FAILURE_EXIT);
- }
- }
- catch (Exception e)
- {
- System.err.println(e.getMessage());
- e.printStackTrace(new PrintStream(System.err));
- System.exit(EXCEPTION_EXIT);
- }
- }
-
- /**
- * Parses a list of test decorators, in the form "class.name[:class.name]*", and creates factories for those
- * TestDecorator classes , and returns a list of the factories. This list of factories will be in the same
- * order as specified in the string. The factories can be used to succesively wrap tests in layers of
- * decorators, as decorators themselves implement the 'Test' interface.
- *
- * <p/>If the string fails to parse, or if any of the decorators specified in it are cannot be loaded, or are not
- * TestDecorators, a runtime exception with a suitable error message will be thrown. The factories themselves
- * throw runtimes if the constructor method calls on the decorators fail.
- *
- * @param decorators The decorators list to be parsed.
- *
- * @return A list of instantiated decorators.
- */
- protected static List<TestDecoratorFactory> parseDecorators(String decorators)
- {
- List<TestDecoratorFactory> result = new LinkedList<TestDecoratorFactory>();
- String toParse = decorators;
-
- // Check that the decorators string is not null or empty, returning an empty list of decorator factories it
- // it is.
- if ((decorators == null) || "".equals(decorators))
- {
- return result;
- }
-
- // Strip any leading and trailing quotes from the string.
- if (toParse.charAt(0) == '\"')
- {
- toParse = toParse.substring(1, toParse.length() - 1);
- }
-
- if (toParse.charAt(toParse.length() - 1) == '\"')
- {
- toParse = toParse.substring(0, toParse.length() - 2);
- }
-
- // Instantiate all decorators.
- for (String decoratorClassName : toParse.split(":"))
- {
- try
- {
- Class decoratorClass = Class.forName(decoratorClassName);
- final Constructor decoratorConstructor = decoratorClass.getConstructor(WrappedSuiteTestDecorator.class);
-
- // Check that the decorator is an instance of WrappedSuiteTestDecorator.
- if (!WrappedSuiteTestDecorator.class.isAssignableFrom(decoratorClass))
- {
- throw new RuntimeException("The decorator class " + decoratorClassName
- + " is not a sub-class of WrappedSuiteTestDecorator, which it needs to be.");
- }
-
- result.add(new TestDecoratorFactory()
- {
- public WrappedSuiteTestDecorator decorateTest(Test test)
- {
- try
- {
- return (WrappedSuiteTestDecorator) decoratorConstructor.newInstance(test);
- }
- catch (InstantiationException e)
- {
- throw new RuntimeException(
- "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
- + " cannot be instantiated.", e);
- }
- catch (IllegalAccessException e)
- {
- throw new RuntimeException(
- "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
- + " does not have a publicly accessable constructor.", e);
- }
- catch (InvocationTargetException e)
- {
- throw new RuntimeException(
- "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
- + " cannot be invoked.", e);
- }
- }
- });
- }
- catch (ClassNotFoundException e)
- {
- throw new RuntimeException("The decorator class " + decoratorClassName + " could not be found.", e);
- }
- catch (NoSuchMethodException e)
- {
- throw new RuntimeException("The decorator class " + decoratorClassName
- + " does not have a constructor that accepts a single 'WrappedSuiteTestDecorator' argument.", e);
- }
- }
-
- return result;
- }
-
- /**
- * TestDecoratorFactory is a factory for creating test decorators from tests.
- */
- protected interface TestDecoratorFactory
- {
- /**
- * Decorates the specified test with a new decorator.
- *
- * @param test The test to decorate.
- *
- * @return The decorated test.
- */
- public WrappedSuiteTestDecorator decorateTest(Test test);
- }
-
- /**
- * Runs a test or suite of tests, using the super class implemenation. This method wraps the test to be run
- * in any test decorators needed to add in the configured toolkits enhanced junit functionality.
- *
- * @param test The test to run.
- * @param wait Undocumented. Nothing in the JUnit javadocs to say what this is for.
- *
- * @return The results of the test run.
- */
- public TestResult doRun(Test test, boolean wait)
- {
- log.debug("public TestResult doRun(Test \"" + test + "\", boolean " + wait + "): called");
-
- // Wrap the tests in decorators for duration, scaling, repetition, parameterization etc.
- WrappedSuiteTestDecorator targetTest = decorateTests(test);
-
- // Delegate to the super method to run the decorated tests.
- log.debug("About to call super.doRun");
-
- TestResult result = super.doRun(targetTest, wait);
- log.debug("super.doRun returned.");
-
- /*if (result instanceof TKTestResult)
- {
- TKTestResult tkResult = (TKTestResult) result;
-
- tkResult.notifyEndBatch();
- }*/
-
- return result;
- }
-
- /**
- * Applies test decorators to the tests for parameterization, duration, scaling and repetition.
- *
- * @param test The test to decorat.
- *
- * @return The decorated test.
- */
- protected WrappedSuiteTestDecorator decorateTests(Test test)
- {
- log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
- log.debug("repetitions = " + repetitions);
- log.debug("threads = " + ((threads == null) ? null : MathUtils.printArray(threads)));
- log.debug("duration = " + duration);
-
- // Wrap all tests in the test suite with WrappedSuiteTestDecorators. This is quite ugly and a bit baffling,
- // but the reason it is done is because the JUnit implementation of TestDecorator has some bugs in it.
- WrappedSuiteTestDecorator targetTest = null;
-
- if (test instanceof TestSuite)
- {
- log.debug("targetTest is a TestSuite");
-
- TestSuite suite = (TestSuite) test;
-
- int numTests = suite.countTestCases();
- log.debug("There are " + numTests + " in the suite.");
-
- for (int i = 0; i < numTests; i++)
- {
- Test nextTest = suite.testAt(i);
- log.debug("suite.testAt(" + i + ") = " + nextTest);
-
- if (nextTest instanceof TimingControllerAware)
- {
- log.debug("nextTest is TimingControllerAware");
- }
-
- if (nextTest instanceof TestThreadAware)
- {
- log.debug("nextTest is TestThreadAware");
- }
- }
-
- targetTest = new WrappedSuiteTestDecorator(suite);
- log.debug("Wrapped with a WrappedSuiteTestDecorator.");
- }
- // If the test has already been wrapped, no need to do it again.
- else if (test instanceof WrappedSuiteTestDecorator)
- {
- targetTest = (WrappedSuiteTestDecorator) test;
- }
-
- // If size parameter values have been set, then wrap the test in an asymptotic test decorator.
- if (params != null)
- {
- targetTest = new AsymptoticTestDecorator(targetTest, params, (repetitions == null) ? 1 : repetitions);
- log.debug("Wrapped with asymptotic test decorator.");
- log.debug("targetTest = " + targetTest);
- }
-
- // If no size parameters are set but the repitions parameter is, then wrap the test in an asymptotic test decorator.
- else if ((repetitions != null) && (repetitions > 1))
- {
- targetTest = new AsymptoticTestDecorator(targetTest, new int[] { 1 }, repetitions);
- log.debug("Wrapped with asymptotic test decorator.");
- log.debug("targetTest = " + targetTest);
- }
-
- // Apply any optional user specified decorators.
- targetTest = applyOptionalUserDecorators(targetTest);
-
- // If a test run duration has been set then wrap the test in a duration test decorator. This will wrap on
- // top of size, repeat or concurrency wrappings already applied.
- if (duration != null)
- {
- DurationTestDecorator durationTest = new DurationTestDecorator(targetTest, duration);
- targetTest = durationTest;
-
- log.debug("Wrapped with duration test decorator.");
- log.debug("targetTest = " + targetTest);
-
- registerShutdownHook(durationTest);
- }
-
- // ParameterVariationTestDecorator...
-
- // If a test thread concurrency level is set then wrap the test in a scaled test decorator. This will wrap on
- // top of size scaling or repetition wrappings.
- ScaledTestDecorator scaledDecorator;
-
- if ((threads != null) && ((threads.length > 1) || (MathUtils.maxInArray(threads) > 1)))
- {
- scaledDecorator = new ScaledTestDecorator(targetTest, threads);
- targetTest = scaledDecorator;
- log.debug("Wrapped with scaled test decorator.");
- log.debug("targetTest = " + targetTest);
- }
- else
- {
- scaledDecorator = new ScaledTestDecorator(targetTest, new int[] { 1 });
- targetTest = scaledDecorator;
- log.debug("Wrapped with scaled test decorator with default of 1 thread.");
- log.debug("targetTest = " + targetTest);
- }
-
- // Register the scaled test decorators shutdown hook.
- registerShutdownHook(scaledDecorator);
-
- return targetTest;
- }
-
- /**
- * If there were any user specified test decorators on the command line, this method instantiates them and wraps
- * the test in them, from inner-most to outer-most in the order in which the decorators were supplied on the
- * command line.
- *
- * @param targetTest The test to wrap.
- *
- * @return A wrapped test.
- */
- protected WrappedSuiteTestDecorator applyOptionalUserDecorators(WrappedSuiteTestDecorator targetTest)
- {
- // If there are user defined test decorators apply them in order now.
- for (TestDecoratorFactory factory : decoratorFactories)
- {
- targetTest = factory.decorateTest(targetTest);
- }
-
- return targetTest;
- }
-
- /**
- * Creates the TestResult object to be used for test runs. See {@link TKTestResult} for more information and the
- * enhanced test result class that this uses.
- *
- * @return An instance of the enhanced test result object, {@link TKTestResult}.
- */
- protected TestResult createTestResult()
- {
- log.debug("protected TestResult createTestResult(): called");
-
- TKTestResult result = new TKTestResult(delay, testCaseName);
-
- // Check if a directory to output reports to has been specified and attach test listeners if so.
- if (reportDir != null)
- {
- // Create the report directory if it does not already exist.
- File reportDirFile = new File(reportDir);
-
- if (!reportDirFile.exists())
- {
- reportDirFile.mkdir();
- }
-
- // Create the results file (make the name of this configurable as a command line parameter).
- Writer timingsWriter;
-
- // Always set up a console feedback listener.
- ConsoleTestListener feedbackListener = new ConsoleTestListener();
- result.addListener(feedbackListener);
- result.addTKTestListener(feedbackListener);
-
- // Set up an XML results listener to output the timings to the results file, if requested on the command line.
- if (xmlResults)
- {
- try
- {
- File timingsFile = new File(reportDirFile, "TEST-" + currentTestClassName + ".xml");
- timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000);
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to create the log file to write test results to: " + e, e);
- }
-
- XMLTestListener listener = new XMLTestListener(timingsWriter, currentTestClassName);
- result.addListener(listener);
- result.addTKTestListener(listener);
-
- registerShutdownHook(listener);
- }
-
- // Set up an CSV results listener to output the timings to the results file, if requested on the command line.
- if (csvResults)
- {
- try
- {
- File timingsFile =
- new File(reportDirFile, testRunName + "-" + TIME_STAMP_FORMAT.format(new Date()) + "-timings.csv");
- timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000);
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to create the log file to write test results to: " + e, e);
- }
-
- CSVTestListener listener = new CSVTestListener(timingsWriter);
- result.addListener(listener);
- result.addTKTestListener(listener);
-
- // Register the results listeners shutdown hook to flush its data if the test framework is shutdown
- // prematurely.
- registerShutdownHook(listener);
- }
-
- // Register the results listeners shutdown hook to flush its data if the test framework is shutdown
- // prematurely.
- // registerShutdownHook(listener);
-
- // Record the start time of the batch.
- // result.notifyStartBatch();
-
- // At this point in time the test class has been instantiated, giving it an opportunity to read its parameters.
- // Inform any test listers of the test properties.
- result.notifyTestProperties(TestContextProperties.getAccessedProps());
- }
-
- return result;
- }
-
- /**
- * Registers the shutdown hook of a {@link ShutdownHookable}.
- *
- * @param hookable The hookable to register.
- */
- protected void registerShutdownHook(ShutdownHookable hookable)
- {
- Runtime.getRuntime().addShutdownHook(hookable.getShutdownHook());
- }
-
- /**
- * Initializes the test runner with the provided command line arguments and and starts the test run.
- *
- * @param testClassName The fully qualified name of the test class to run.
- *
- * @return The test results.
- *
- * @throws Exception Any exceptions from running the tests are allowed to fall through.
- */
- protected TestResult start(String testClassName) throws Exception
- {
- // Record the current test class, so that the test results can be output to a file incorporating this name.
- this.currentTestClassName = testClassName;
-
- // Delegate to the super method to run the tests.
- return super.start(new String[] { testClassName });
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.listeners.CSVTestListener;
+import org.apache.qpid.junit.extensions.listeners.ConsoleTestListener;
+import org.apache.qpid.junit.extensions.listeners.XMLTestListener;
+import org.apache.qpid.junit.extensions.util.CommandLineParser;
+import org.apache.qpid.junit.extensions.util.MathUtils;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import java.io.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * TKTestRunner extends {@link junit.textui.TestRunner} with the ability to run tests multiple times, to execute a test
+ * simultaneously using many threads, to put a delay between test runs and adds support for tests that take integer
+ * parameters that can be 'stepped' through on multiple test runs. These features can be accessed by using this class
+ * as an entry point and passing command line arguments to specify which features to use:
+ *
+ * <pre>
+ * -w ms The number of milliseconds between invocations of test cases.
+ * -c pattern The number of tests to run concurrently.
+ * -r num The number of times to repeat each test.
+ * -d duration The length of time to run the tests for.
+ * -t name The name of the test case to execute.
+ * -s pattern The size parameter to run tests with.
+ * -o dir The name of the directory to output test timings to.
+ * --csv Output test results in CSV format.
+ * --xml Output test results in XML format.
+ * </pre>
+ *
+ * <p/>This command line may also have trailing 'name=value' parameters added to it. All of these values are added
+ * to the test context properties and passed to the test, which can access them by name.
+ *
+ * <p/>The pattern arguments are of the form [lowest(: ...)(: highest)](:sample=s)(:exp), where round brackets
+ * enclose optional values. Using this pattern form it is possible to specify a single value, a range of values divided
+ * into s samples, a range of values divided into s samples but distributed exponentially, or a fixed set of samples.
+ *
+ * <p/>The duration arguments are of the form (dD)(hH)(mM)(sS), where round brackets enclose optional values. At least
+ * one of the optional values must be present.
+ *
+ * <p/>When specifying optional test parameters on the command line, in 'name=value' format, it is also possible to use
+ * the format 'name=[value1:value2:value3:...]', to specify multiple values for a parameter. All permutations of all
+ * parameters with multiple values will be created and tested. If the values are numerical, it is also possible to use
+ * the sequence generation patterns instead of fully specifying all of the values.
+ *
+ * <p/>Here are some examples:
+ *
+ * <p/><table>
+ * <tr><td><pre> -c [10:20:30:40:50] </pre><td> Runs the test with 10,20,...,50 threads.
+ * <tr><td><pre> -s [1:100]:samples=10 </pre>
+ * <td> Runs the test with ten different size parameters evenly spaced between 1 and 100.
+ * <tr><td><pre> -s [1:1000000]:samples=10:exp </pre>
+ * <td> Runs the test with ten different size parameters exponentially spaced between 1 and 1000000.
+ * <tr><td><pre> -r 10 </pre><td> Runs each test ten times.
+ * <tr><td><pre> -d 10H </pre><td> Runs the test repeatedly for 10 hours.
+ * <tr><td><pre> -d 1M, -r 10 </pre>
+ * <td> Runs the test repeatedly for 1 minute but only takes a timing sample every 10 test runs.
+ * <tr><td><pre> -r 10, -c [1:5:10:50], -s [100:1000:10000] </pre>
+ * <td> Runs 12 test cycles (4 concurrency samples * 3 size sample), with 10 repeats each. In total the test
+ * will be run 199 times (3 + 15 + 30 + 150)
+ * <tr><td><pre> cache=true </pre><td> Passes the 'cache' parameter with value 'true' to the test.
+ * <tr><td><pre> cache=[true:false] </pre><td> Runs the test with the 'cache' parameter set to 'true' and 'false'.
+ * <tr><td><pre> cacheSize=[1000:1000000],samples=4,exp </pre>
+ * <td> Runs the test with the 'cache' parameter set to a series of exponentially increasing sizes.
+ * </table>
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create the test configuration specified by the command line parameters.
+ * </table>
+ *
+ * @todo Verify that the output directory exists or can be created.
+ *
+ * @todo Verify that the specific named test case to execute exists.
+ *
+ * @todo Drop the delay parameter as it is being replaced by throttling.
+ *
+ * @todo Completely replace the test ui test runner, instead of having TKTestRunner inherit from it, its just not
+ * good code to extend.
+ *
+ * @author Rupert Smith
+ */
+public class TKTestRunner extends TestRunnerImprovedErrorHandling
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TKTestRunner.class);
+
+ /** Used for displaying information on the console. */
+ // private static final Logger console = Logger.getLogger("CONSOLE." + TKTestRunner.class.getName());
+
+ /** Used for generating the timestamp when naming output files. */
+ protected static final DateFormat TIME_STAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
+
+ /** Number of times to rerun the test. */
+ protected Integer repetitions = 1;
+
+ /** The length of time to run the tests for. */
+ protected Long duration;
+
+ /** Number of threads running the tests. */
+ protected int[] threads;
+
+ /** Delay in ms to wait between two test cases. */
+ protected int delay = 0;
+
+ /** The parameter values to pass to parameterized tests. */
+ protected int[] params;
+
+ /** Name of the single test case to execute. */
+ protected String testCaseName = null;
+
+ /** Name of the test class. */
+ protected String testClassName = null;
+
+ /** Name of the test run. */
+ protected String testRunName = null;
+
+ /** Directory to output XML reports into, if specified. */
+ protected String reportDir = null;
+
+ /** Flag that indicates the CSV results listener should be used to output results. */
+ protected boolean csvResults;
+
+ /** Flag that indiciates the XML results listener should be used to output results. */
+ protected boolean xmlResults;
+
+ /**
+ * Holds the name of the class of the test currently being run. Ideally passed into the {@link #createTestResult}
+ * method, but as the signature is already fixed for this, the current value gets pushed here as a member variable.
+ */
+ protected String currentTestClassName;
+
+ /** Holds the test results object, which is reponsible for instrumenting tests/threads to record results. */
+ protected TKTestResult result;
+
+ /** Holds a list of factories for instantiating optional user specified test decorators. */
+ protected List<TestDecoratorFactory> decoratorFactories;
+
+ /**
+ * Constructs a TKTestRunner using System.out for all the output.
+ *
+ * @param repetitions The number of times to repeat the test, or test batch size.
+ * @param duration The length of time to run the tests for. -1 means no duration has been set.
+ * @param threads The concurrency levels to ramp up to.
+ * @param delay A delay in milliseconds between test runs.
+ * @param params The sets of 'size' parameters to pass to test.
+ * @param testCaseName The name of the test case to run.
+ * @param reportDir The directory to output the test results to.
+ * @param runName The name of the test run; used to name the output file.
+ * @param csvResults <tt>true</tt> if the CSV results listener should be attached.
+ * @param xmlResults <tt>true</tt> if the XML results listener should be attached.
+ * @param decoratorFactories List of factories for user specified decorators.
+ */
+ public TKTestRunner(Integer repetitions, Long duration, int[] threads, int delay, int[] params, String testCaseName,
+ String reportDir, String runName, boolean csvResults, boolean xmlResults,
+ List<TestDecoratorFactory> decoratorFactories)
+ {
+ super(new NullResultPrinter(System.out));
+
+ log.debug("public TKTestRunner(): called");
+
+ // Keep all the test parameters.
+ this.repetitions = repetitions;
+ this.duration = duration;
+ this.threads = threads;
+ this.delay = delay;
+ this.params = params;
+ this.testCaseName = testCaseName;
+ this.reportDir = reportDir;
+ this.testRunName = runName;
+ this.csvResults = csvResults;
+ this.xmlResults = xmlResults;
+ this.decoratorFactories = decoratorFactories;
+ }
+
+ /**
+ * The entry point for the toolkit test runner.
+ *
+ * @param args The command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ // Use the command line parser to evaluate the command line.
+ CommandLineParser commandLine =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "w", "The number of milliseconds between invocations of test cases.", "ms", "false" },
+ { "c", "The number of tests to run concurrently.", "num", "false", MathUtils.SEQUENCE_REGEXP },
+ { "r", "The number of times to repeat each test.", "num", "false" },
+ { "d", "The length of time to run the tests for.", "duration", "false", MathUtils.DURATION_REGEXP },
+ { "f", "The maximum rate to call the tests at.", "frequency", "false", "^([1-9][0-9]*)/([1-9][0-9]*)$" },
+ { "s", "The size parameter to run tests with.", "size", "false", MathUtils.SEQUENCE_REGEXP },
+ { "t", "The name of the test case to execute.", "name", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ { "n", "A name for this test run, used to name the output file.", "name", "true" },
+ {
+ "X:decorators", "A list of additional test decorators to wrap the tests in.",
+ "\"class.name[:class.name]*\"", "false"
+ },
+ { "1", "Test class.", "class", "true" },
+ { "-csv", "Output test results in CSV format.", null, "false" },
+ { "-xml", "Output test results in XML format.", null, "false" }
+ });
+
+ // Capture the command line arguments or display errors and correct usage and then exit.
+ ParsedProperties options = null;
+
+ try
+ {
+ options = new ParsedProperties(commandLine.parseCommandLine(args));
+ }
+ catch (IllegalArgumentException e)
+ {
+ System.out.println(commandLine.getErrors());
+ System.out.println(commandLine.getUsage());
+ System.exit(FAILURE_EXIT);
+ }
+
+ // Extract the command line options.
+ Integer delay = options.getPropertyAsInteger("w");
+ String threadsString = options.getProperty("c");
+ Integer repetitions = options.getPropertyAsInteger("r");
+ String durationString = options.getProperty("d");
+ String paramsString = options.getProperty("s");
+ String testCaseName = options.getProperty("t");
+ String reportDir = options.getProperty("o");
+ String testRunName = options.getProperty("n");
+ String decorators = options.getProperty("X:decorators");
+ String testClassName = options.getProperty("1");
+ boolean csvResults = options.getPropertyAsBoolean("-csv");
+ boolean xmlResults = options.getPropertyAsBoolean("-xml");
+
+ int[] threads = (threadsString == null) ? null : MathUtils.parseSequence(threadsString);
+ int[] params = (paramsString == null) ? null : MathUtils.parseSequence(paramsString);
+ Long duration = (durationString == null) ? null : MathUtils.parseDuration(durationString);
+
+ // The test run name defaults to the test class name unless a value was specified for it.
+ testRunName = (testRunName == null) ? testClassName : testRunName;
+
+ // Add all the command line options and trailing settings to test context properties. Tests may pick up
+ // overridden values from there, and these values will be logged in the test results, for analysis and
+ // to make tests repeatable.
+ commandLine.addTrailingPairsToProperties(TestContextProperties.getInstance());
+ commandLine.addOptionsToProperties(TestContextProperties.getInstance());
+
+ // Create and start the test runner.
+ try
+ {
+ // Create a list of test decorator factories for use specified decorators to be applied.
+ List<TestDecoratorFactory> decoratorFactories = parseDecorators(decorators);
+
+ TKTestRunner testRunner =
+ new TKTestRunner(repetitions, duration, threads, (delay == null) ? 0 : delay, params, testCaseName,
+ reportDir, testRunName, csvResults, xmlResults, decoratorFactories);
+
+ TestResult testResult = testRunner.start(testClassName);
+
+ if (!testResult.wasSuccessful())
+ {
+ System.exit(FAILURE_EXIT);
+ }
+ }
+ catch (Exception e)
+ {
+ System.err.println(e.getMessage());
+ e.printStackTrace(new PrintStream(System.err));
+ System.exit(EXCEPTION_EXIT);
+ }
+ }
+
+ /**
+ * Parses a list of test decorators, in the form "class.name[:class.name]*", and creates factories for those
+ * TestDecorator classes , and returns a list of the factories. This list of factories will be in the same
+ * order as specified in the string. The factories can be used to succesively wrap tests in layers of
+ * decorators, as decorators themselves implement the 'Test' interface.
+ *
+ * <p/>If the string fails to parse, or if any of the decorators specified in it are cannot be loaded, or are not
+ * TestDecorators, a runtime exception with a suitable error message will be thrown. The factories themselves
+ * throw runtimes if the constructor method calls on the decorators fail.
+ *
+ * @param decorators The decorators list to be parsed.
+ *
+ * @return A list of instantiated decorators.
+ */
+ protected static List<TestDecoratorFactory> parseDecorators(String decorators)
+ {
+ List<TestDecoratorFactory> result = new LinkedList<TestDecoratorFactory>();
+ String toParse = decorators;
+
+ // Check that the decorators string is not null or empty, returning an empty list of decorator factories it
+ // it is.
+ if ((decorators == null) || "".equals(decorators))
+ {
+ return result;
+ }
+
+ // Strip any leading and trailing quotes from the string.
+ if (toParse.charAt(0) == '\"')
+ {
+ toParse = toParse.substring(1, toParse.length() - 1);
+ }
+
+ if (toParse.charAt(toParse.length() - 1) == '\"')
+ {
+ toParse = toParse.substring(0, toParse.length() - 2);
+ }
+
+ // Instantiate all decorators.
+ for (String decoratorClassName : toParse.split(":"))
+ {
+ try
+ {
+ Class decoratorClass = Class.forName(decoratorClassName);
+ final Constructor decoratorConstructor = decoratorClass.getConstructor(WrappedSuiteTestDecorator.class);
+
+ // Check that the decorator is an instance of WrappedSuiteTestDecorator.
+ if (!WrappedSuiteTestDecorator.class.isAssignableFrom(decoratorClass))
+ {
+ throw new RuntimeException("The decorator class " + decoratorClassName
+ + " is not a sub-class of WrappedSuiteTestDecorator, which it needs to be.");
+ }
+
+ result.add(new TestDecoratorFactory()
+ {
+ public WrappedSuiteTestDecorator decorateTest(Test test)
+ {
+ try
+ {
+ return (WrappedSuiteTestDecorator) decoratorConstructor.newInstance(test);
+ }
+ catch (InstantiationException e)
+ {
+ throw new RuntimeException(
+ "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
+ + " cannot be instantiated.", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new RuntimeException(
+ "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
+ + " does not have a publicly accessable constructor.", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new RuntimeException(
+ "The decorator class " + decoratorConstructor.getDeclaringClass().getName()
+ + " cannot be invoked.", e);
+ }
+ }
+ });
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new RuntimeException("The decorator class " + decoratorClassName + " could not be found.", e);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new RuntimeException("The decorator class " + decoratorClassName
+ + " does not have a constructor that accepts a single 'WrappedSuiteTestDecorator' argument.", e);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * TestDecoratorFactory is a factory for creating test decorators from tests.
+ */
+ protected interface TestDecoratorFactory
+ {
+ /**
+ * Decorates the specified test with a new decorator.
+ *
+ * @param test The test to decorate.
+ *
+ * @return The decorated test.
+ */
+ public WrappedSuiteTestDecorator decorateTest(Test test);
+ }
+
+ /**
+ * Runs a test or suite of tests, using the super class implemenation. This method wraps the test to be run
+ * in any test decorators needed to add in the configured toolkits enhanced junit functionality.
+ *
+ * @param test The test to run.
+ * @param wait Undocumented. Nothing in the JUnit javadocs to say what this is for.
+ *
+ * @return The results of the test run.
+ */
+ public TestResult doRun(Test test, boolean wait)
+ {
+ log.debug("public TestResult doRun(Test \"" + test + "\", boolean " + wait + "): called");
+
+ // Wrap the tests in decorators for duration, scaling, repetition, parameterization etc.
+ WrappedSuiteTestDecorator targetTest = decorateTests(test);
+
+ // Delegate to the super method to run the decorated tests.
+ log.debug("About to call super.doRun");
+
+ TestResult result = super.doRun(targetTest, wait);
+ log.debug("super.doRun returned.");
+
+ /*if (result instanceof TKTestResult)
+ {
+ TKTestResult tkResult = (TKTestResult) result;
+
+ tkResult.notifyEndBatch();
+ }*/
+
+ return result;
+ }
+
+ /**
+ * Applies test decorators to the tests for parameterization, duration, scaling and repetition.
+ *
+ * @param test The test to decorat.
+ *
+ * @return The decorated test.
+ */
+ protected WrappedSuiteTestDecorator decorateTests(Test test)
+ {
+ log.debug("params = " + ((params == null) ? null : MathUtils.printArray(params)));
+ log.debug("repetitions = " + repetitions);
+ log.debug("threads = " + ((threads == null) ? null : MathUtils.printArray(threads)));
+ log.debug("duration = " + duration);
+
+ // Wrap all tests in the test suite with WrappedSuiteTestDecorators. This is quite ugly and a bit baffling,
+ // but the reason it is done is because the JUnit implementation of TestDecorator has some bugs in it.
+ WrappedSuiteTestDecorator targetTest = null;
+
+ if (test instanceof TestSuite)
+ {
+ log.debug("targetTest is a TestSuite");
+
+ TestSuite suite = (TestSuite) test;
+
+ int numTests = suite.countTestCases();
+ log.debug("There are " + numTests + " in the suite.");
+
+ for (int i = 0; i < numTests; i++)
+ {
+ Test nextTest = suite.testAt(i);
+ log.debug("suite.testAt(" + i + ") = " + nextTest);
+
+ if (nextTest instanceof TimingControllerAware)
+ {
+ log.debug("nextTest is TimingControllerAware");
+ }
+
+ if (nextTest instanceof TestThreadAware)
+ {
+ log.debug("nextTest is TestThreadAware");
+ }
+ }
+
+ targetTest = new WrappedSuiteTestDecorator(suite);
+ log.debug("Wrapped with a WrappedSuiteTestDecorator.");
+ }
+ // If the test has already been wrapped, no need to do it again.
+ else if (test instanceof WrappedSuiteTestDecorator)
+ {
+ targetTest = (WrappedSuiteTestDecorator) test;
+ }
+
+ // If size parameter values have been set, then wrap the test in an asymptotic test decorator.
+ if (params != null)
+ {
+ targetTest = new AsymptoticTestDecorator(targetTest, params, (repetitions == null) ? 1 : repetitions);
+ log.debug("Wrapped with asymptotic test decorator.");
+ log.debug("targetTest = " + targetTest);
+ }
+
+ // If no size parameters are set but the repitions parameter is, then wrap the test in an asymptotic test decorator.
+ else if ((repetitions != null) && (repetitions > 1))
+ {
+ targetTest = new AsymptoticTestDecorator(targetTest, new int[] { 1 }, repetitions);
+ log.debug("Wrapped with asymptotic test decorator.");
+ log.debug("targetTest = " + targetTest);
+ }
+
+ // Apply any optional user specified decorators.
+ targetTest = applyOptionalUserDecorators(targetTest);
+
+ // If a test run duration has been set then wrap the test in a duration test decorator. This will wrap on
+ // top of size, repeat or concurrency wrappings already applied.
+ if (duration != null)
+ {
+ DurationTestDecorator durationTest = new DurationTestDecorator(targetTest, duration);
+ targetTest = durationTest;
+
+ log.debug("Wrapped with duration test decorator.");
+ log.debug("targetTest = " + targetTest);
+
+ registerShutdownHook(durationTest);
+ }
+
+ // ParameterVariationTestDecorator...
+
+ // If a test thread concurrency level is set then wrap the test in a scaled test decorator. This will wrap on
+ // top of size scaling or repetition wrappings.
+ ScaledTestDecorator scaledDecorator;
+
+ if ((threads != null) && ((threads.length > 1) || (MathUtils.maxInArray(threads) > 1)))
+ {
+ scaledDecorator = new ScaledTestDecorator(targetTest, threads);
+ targetTest = scaledDecorator;
+ log.debug("Wrapped with scaled test decorator.");
+ log.debug("targetTest = " + targetTest);
+ }
+ else
+ {
+ scaledDecorator = new ScaledTestDecorator(targetTest, new int[] { 1 });
+ targetTest = scaledDecorator;
+ log.debug("Wrapped with scaled test decorator with default of 1 thread.");
+ log.debug("targetTest = " + targetTest);
+ }
+
+ // Register the scaled test decorators shutdown hook.
+ registerShutdownHook(scaledDecorator);
+
+ return targetTest;
+ }
+
+ /**
+ * If there were any user specified test decorators on the command line, this method instantiates them and wraps
+ * the test in them, from inner-most to outer-most in the order in which the decorators were supplied on the
+ * command line.
+ *
+ * @param targetTest The test to wrap.
+ *
+ * @return A wrapped test.
+ */
+ protected WrappedSuiteTestDecorator applyOptionalUserDecorators(WrappedSuiteTestDecorator targetTest)
+ {
+ // If there are user defined test decorators apply them in order now.
+ for (TestDecoratorFactory factory : decoratorFactories)
+ {
+ targetTest = factory.decorateTest(targetTest);
+ }
+
+ return targetTest;
+ }
+
+ /**
+ * Creates the TestResult object to be used for test runs. See {@link TKTestResult} for more information and the
+ * enhanced test result class that this uses.
+ *
+ * @return An instance of the enhanced test result object, {@link TKTestResult}.
+ */
+ protected TestResult createTestResult()
+ {
+ log.debug("protected TestResult createTestResult(): called");
+
+ TKTestResult result = new TKTestResult(delay, testCaseName);
+
+ // Check if a directory to output reports to has been specified and attach test listeners if so.
+ if (reportDir != null)
+ {
+ // Create the report directory if it does not already exist.
+ File reportDirFile = new File(reportDir);
+
+ if (!reportDirFile.exists())
+ {
+ reportDirFile.mkdir();
+ }
+
+ // Create the results file (make the name of this configurable as a command line parameter).
+ Writer timingsWriter;
+
+ // Always set up a console feedback listener.
+ ConsoleTestListener feedbackListener = new ConsoleTestListener();
+ result.addListener(feedbackListener);
+ result.addTKTestListener(feedbackListener);
+
+ // Set up an XML results listener to output the timings to the results file, if requested on the command line.
+ if (xmlResults)
+ {
+ try
+ {
+ File timingsFile = new File(reportDirFile, "TEST-" + currentTestClassName + ".xml");
+ timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to create the log file to write test results to: " + e, e);
+ }
+
+ XMLTestListener listener = new XMLTestListener(timingsWriter, currentTestClassName);
+ result.addListener(listener);
+ result.addTKTestListener(listener);
+
+ registerShutdownHook(listener);
+ }
+
+ // Set up an CSV results listener to output the timings to the results file, if requested on the command line.
+ if (csvResults)
+ {
+ try
+ {
+ File timingsFile =
+ new File(reportDirFile, testRunName + "-" + TIME_STAMP_FORMAT.format(new Date()) + "-timings.csv");
+ timingsWriter = new BufferedWriter(new FileWriter(timingsFile), 20000);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to create the log file to write test results to: " + e, e);
+ }
+
+ CSVTestListener listener = new CSVTestListener(timingsWriter);
+ result.addListener(listener);
+ result.addTKTestListener(listener);
+
+ // Register the results listeners shutdown hook to flush its data if the test framework is shutdown
+ // prematurely.
+ registerShutdownHook(listener);
+ }
+
+ // Register the results listeners shutdown hook to flush its data if the test framework is shutdown
+ // prematurely.
+ // registerShutdownHook(listener);
+
+ // Record the start time of the batch.
+ // result.notifyStartBatch();
+
+ // At this point in time the test class has been instantiated, giving it an opportunity to read its parameters.
+ // Inform any test listers of the test properties.
+ result.notifyTestProperties(TestContextProperties.getAccessedProps());
+ }
+
+ return result;
+ }
+
+ /**
+ * Registers the shutdown hook of a {@link ShutdownHookable}.
+ *
+ * @param hookable The hookable to register.
+ */
+ protected void registerShutdownHook(ShutdownHookable hookable)
+ {
+ Runtime.getRuntime().addShutdownHook(hookable.getShutdownHook());
+ }
+
+ /**
+ * Initializes the test runner with the provided command line arguments and and starts the test run.
+ *
+ * @param testClassName The fully qualified name of the test class to run.
+ *
+ * @return The test results.
+ *
+ * @throws Exception Any exceptions from running the tests are allowed to fall through.
+ */
+ protected TestResult start(String testClassName) throws Exception
+ {
+ // Record the current test class, so that the test results can be output to a file incorporating this name.
+ this.currentTestClassName = testClassName;
+
+ // Delegate to the super method to run the tests.
+ return super.start(new String[] { testClassName });
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
index 9b4a8707db..edd79b3697 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestRunnerImprovedErrorHandling.java
@@ -1,131 +1,131 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import junit.runner.Version;
-
-import junit.textui.ResultPrinter;
-import junit.textui.TestRunner;
-
-import org.apache.log4j.Logger;
-
-import java.io.PrintStream;
-
-/**
- * The {@link junit.textui.TestRunner} does not provide very good error handling. It does not wrap exceptions and
- * does not print out stack traces, losing valuable error tracing information. This class overrides methods in it
- * in order to improve their error handling. The {@link TKTestRunner} is then built on top of this.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- */
-public class TestRunnerImprovedErrorHandling extends TestRunner
-{
- /** Used for logging. */
- Logger log = Logger.getLogger(TestRunnerImprovedErrorHandling.class);
-
- /**
- * Delegates to the super constructor.
- */
- public TestRunnerImprovedErrorHandling()
- {
- super();
- }
-
- /**
- * Delegates to the super constructor.
- *
- * @param printStream The location to write test results to.
- */
- public TestRunnerImprovedErrorHandling(PrintStream printStream)
- {
- super(printStream);
- }
-
- /**
- * Delegates to the super constructor.
- *
- * @param resultPrinter The location to write test results to.
- */
- public TestRunnerImprovedErrorHandling(ResultPrinter resultPrinter)
- {
- super(resultPrinter);
- }
-
- /**
- * Starts a test run. Analyzes the command line arguments
- * and runs the given test suite.
- *
- * @param args The command line arguments.
- *
- * @return The test results.
- *
- * @throws Exception Any exceptions falling through the tests are wrapped in Exception and rethrown.
- */
- protected TestResult start(String[] args) throws Exception
- {
- String testCase = "";
- boolean wait = false;
-
- for (int i = 0; i < args.length; i++)
- {
- if (args[i].equals("-wait"))
- {
- wait = true;
- }
- else if (args[i].equals("-c"))
- {
- testCase = extractClassName(args[++i]);
- }
- else if (args[i].equals("-v"))
- {
- System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
- }
- else
- {
- testCase = args[i];
- }
- }
-
- if (testCase.equals(""))
- {
- throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
- }
-
- try
- {
- Test suite = getTest(testCase);
-
- return doRun(suite, wait);
- }
- catch (Exception e)
- {
- log.warn("Got exception whilst creating and running test suite.", e);
- throw new Exception("Could not create and run the test suite.", e);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import junit.runner.Version;
+
+import junit.textui.ResultPrinter;
+import junit.textui.TestRunner;
+
+import org.apache.log4j.Logger;
+
+import java.io.PrintStream;
+
+/**
+ * The {@link junit.textui.TestRunner} does not provide very good error handling. It does not wrap exceptions and
+ * does not print out stack traces, losing valuable error tracing information. This class overrides methods in it
+ * in order to improve their error handling. The {@link TKTestRunner} is then built on top of this.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class TestRunnerImprovedErrorHandling extends TestRunner
+{
+ /** Used for logging. */
+ Logger log = Logger.getLogger(TestRunnerImprovedErrorHandling.class);
+
+ /**
+ * Delegates to the super constructor.
+ */
+ public TestRunnerImprovedErrorHandling()
+ {
+ super();
+ }
+
+ /**
+ * Delegates to the super constructor.
+ *
+ * @param printStream The location to write test results to.
+ */
+ public TestRunnerImprovedErrorHandling(PrintStream printStream)
+ {
+ super(printStream);
+ }
+
+ /**
+ * Delegates to the super constructor.
+ *
+ * @param resultPrinter The location to write test results to.
+ */
+ public TestRunnerImprovedErrorHandling(ResultPrinter resultPrinter)
+ {
+ super(resultPrinter);
+ }
+
+ /**
+ * Starts a test run. Analyzes the command line arguments
+ * and runs the given test suite.
+ *
+ * @param args The command line arguments.
+ *
+ * @return The test results.
+ *
+ * @throws Exception Any exceptions falling through the tests are wrapped in Exception and rethrown.
+ */
+ protected TestResult start(String[] args) throws Exception
+ {
+ String testCase = "";
+ boolean wait = false;
+
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].equals("-wait"))
+ {
+ wait = true;
+ }
+ else if (args[i].equals("-c"))
+ {
+ testCase = extractClassName(args[++i]);
+ }
+ else if (args[i].equals("-v"))
+ {
+ System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
+ }
+ else
+ {
+ testCase = args[i];
+ }
+ }
+
+ if (testCase.equals(""))
+ {
+ throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
+ }
+
+ try
+ {
+ Test suite = getTest(testCase);
+
+ return doRun(suite, wait);
+ }
+ catch (Exception e)
+ {
+ log.warn("Got exception whilst creating and running test suite.", e);
+ throw new Exception("Could not create and run the test suite.", e);
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java
index aaa773260d..d7de2822a2 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TestThreadAware.java
@@ -1,49 +1,49 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-/**
- * This interface can be implemented by tests that want to know if they are being run concurrently. It provides
- * lifecycle notification events to tell the test implementation when test threads are being created and destroyed.
- * This can assist tests in creating and destroying resources that exist over the life of a test thread. A single
- * test thread can excute the same test many times, and often it is convenient to keep resources, for example network
- * connections, open over many test calls.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Set up per thread test fixtures.
- * <tr><td> Clean up per thread test fixtures.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface TestThreadAware
-{
- /**
- * Called when a test thread is created.
- */
- public void threadSetUp();
-
- /**
- * Called when a test thread is destroyed.
- */
- public void threadTearDown();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * This interface can be implemented by tests that want to know if they are being run concurrently. It provides
+ * lifecycle notification events to tell the test implementation when test threads are being created and destroyed.
+ * This can assist tests in creating and destroying resources that exist over the life of a test thread. A single
+ * test thread can excute the same test many times, and often it is convenient to keep resources, for example network
+ * connections, open over many test calls.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Set up per thread test fixtures.
+ * <tr><td> Clean up per thread test fixtures.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface TestThreadAware
+{
+ /**
+ * Called when a test thread is created.
+ */
+ public void threadSetUp();
+
+ /**
+ * Called when a test thread is destroyed.
+ */
+ public void threadTearDown();
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java
index 955e47c25b..1ea8e8e2be 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/Throttle.java
@@ -1,73 +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.junit.extensions;
-
-/**
- * Throttle is an interface that supplies a {@link #throttle} method, that can only be called at the rate specified
- * in a call to the {@link #setRate} method. This can be used to restict processing to run at a certain number
- * of operations per second.
- *
- * <p/>Throttle also supplies a method to check the throttle rate, without waiting. This could be used to update a user
- * interface every time an event occurs, but only up to a maximum rate. For example, as elements are added to a list,
- * a count of elements is updated for the user to see, but only up to a maximum rate of ten updates a second, as updating
- * faster than that slows the processing of element-by-element additions to the list unnecessarily.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Accept throttling rate in operations per second.
- * <tr><td> Inject short pauses to fill-out processing cycles to a specified rate.
- * <tr><td> Check against a throttle speed without waiting.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface Throttle
-{
- /**
- * Specifies the throttling rate in operations per second. This must be called with with a value, the inverse
- * of which is a measurement in nano seconds, such that the number of nano seconds do not overflow a long integer.
- * The value must also be larger than zero.
- *
- * @param hertz The throttling rate in cycles per second.
- */
- public void setRate(float hertz);
-
- /**
- * This method can only be called at the rate set by the {@link #setRate} method, if it is called faster than this
- * it will inject short pauses to restrict the call rate to that rate.
- *
- * <p/>If the thread executing this method is interrupted, it must ensure that the threads interrupt thread
- * remains set upon exit from the method. This method does not expose InterruptedException, to indicate interruption
- * of the throttle during a timed wait. It may be changed so that it does.
- */
- public void throttle();
-
- /**
- * Checks but does not enforce the throttle rate. When this method is called, it checks if a length of time greater
- * than that equal to the inverse of the throttling rate has passed since it was last called and returned <tt>true</tt>
- *
- * @return <tt>true</tt> if a length of time greater than that equal to the inverse of the throttling rate has
- * passed since this method was last called and returned <tt>true</tt>, <tt>false</tt> otherwise. The very
- * first time this method is called on a throttle, it returns <tt>true</tt> as the base case to the above
- * self-referential definition.
- */
- public boolean checkThrottle();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * Throttle is an interface that supplies a {@link #throttle} method, that can only be called at the rate specified
+ * in a call to the {@link #setRate} method. This can be used to restict processing to run at a certain number
+ * of operations per second.
+ *
+ * <p/>Throttle also supplies a method to check the throttle rate, without waiting. This could be used to update a user
+ * interface every time an event occurs, but only up to a maximum rate. For example, as elements are added to a list,
+ * a count of elements is updated for the user to see, but only up to a maximum rate of ten updates a second, as updating
+ * faster than that slows the processing of element-by-element additions to the list unnecessarily.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Accept throttling rate in operations per second.
+ * <tr><td> Inject short pauses to fill-out processing cycles to a specified rate.
+ * <tr><td> Check against a throttle speed without waiting.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface Throttle
+{
+ /**
+ * Specifies the throttling rate in operations per second. This must be called with with a value, the inverse
+ * of which is a measurement in nano seconds, such that the number of nano seconds do not overflow a long integer.
+ * The value must also be larger than zero.
+ *
+ * @param hertz The throttling rate in cycles per second.
+ */
+ public void setRate(float hertz);
+
+ /**
+ * This method can only be called at the rate set by the {@link #setRate} method, if it is called faster than this
+ * it will inject short pauses to restrict the call rate to that rate.
+ *
+ * <p/>If the thread executing this method is interrupted, it must ensure that the threads interrupt thread
+ * remains set upon exit from the method. This method does not expose InterruptedException, to indicate interruption
+ * of the throttle during a timed wait. It may be changed so that it does.
+ */
+ public void throttle();
+
+ /**
+ * Checks but does not enforce the throttle rate. When this method is called, it checks if a length of time greater
+ * than that equal to the inverse of the throttling rate has passed since it was last called and returned <tt>true</tt>
+ *
+ * @return <tt>true</tt> if a length of time greater than that equal to the inverse of the throttling rate has
+ * passed since this method was last called and returned <tt>true</tt>, <tt>false</tt> otherwise. The very
+ * first time this method is called on a throttle, it returns <tt>true</tt> as the base case to the above
+ * self-referential definition.
+ */
+ public boolean checkThrottle();
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java
index 7b5763f1de..b69df84045 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingController.java
@@ -1,175 +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.junit.extensions;
-
-/**
- * A TimingController is a interface that a test that is aware of the fact that it is being timed can use to manage
- * the timer. Using this interface tests can suspend and resume test timers. This is usefull if you want to exclude
- * some expensive preparation from being timed as part of a test. In general when timing tests to measure the
- * performance of code, you should try to set up data in the #setUp where possible, or as static members in the test
- * class. This is not always convenient, this interface gives you a way to suspend and resume, or event completely
- * restart test timers, to get accurate measurements.
- *
- * <p/>The interface can also be used to register multiple test pass/fails and timings from a single test method.
- * In some cases it is easier to write tests in this way. For example a concurrent and asynchronous test may make
- * many asynchronous requests and then wait for replies to all its requests. Writing such a test with one send/reply
- * per test method and trying to scale up using many threads will quickly run into limitations if more than about
- * 100 asynchronous calls need to be made at once. A better way to write such a test is as a single method that sends
- * many (perhaps thousands or millions) and waits for replies in two threads, one for send, one for replies. It can
- * then log pass/fails and timings on each individual reply as they come back in, even though the test has been written
- * to send thousands of requests per test method in order to do volume testing.
- *
- * <p/>If when the {@link #completeTest(boolean)} is called, the test runner decides that testing should stop (perhaps
- * because a duration test has expired), it throws an InterruptedException to indicate that the test method should stop
- * immediately. The test method can do this by allowing this exception to fall through, if no other clean-up handling
- * is necessary, or it can simply return as soon as it possibly can. The test runner will still call the tearDown
- * method in the usual way when this happens.
- *
- * <p/>Below are some examples of how this can be used. Not how checking that the timing controller is really available
- * rather than assuming it is, means that the test can run as an ordinary JUnit test under the default test runners. In
- * general code should be written to take advantage of the extended capabilities of junit toolkit, without assuming they
- * are going to be run under its test runner.
- *
- * <pre>
- * public class MyTest extends TestCase implements TimingControllerAware {
- * ...
- *
- * timingUtils = this.getTimingController();
- *
- * // Do expensive data preparation here...
- *
- * if (timingUtils != null)
- * timingUtils.restart();
- * </pre>
- *
- * <pre>
- * public class MyTest extends TestCase implements TimingControllerAware {
- * ...
- *
- * public void myVolumeTest(int size) {
- *
- * timingUtils = this.getTimingController();
- *
- * boolean stopNow = false;
- *
- * // In Sender thread.
- * for(int i = 0; !stopNow && i < size; i++)
- * // Send request i.
- * ...
- *
- * // In Receiver thread.
- * onReceive(Object o) {
- * try {
- * // Check o is as expected.
- * if (....)
- * {
- * if (timingUtils != null)
- * timingUtils.completeTest(true);
- * }
- * else
- * {
- * if (timingUtils != null)
- * timingUtils.completeTest(false);
- * }
- * } catch (InterruptedException e) {
- * stopNow = true;
- * return;
- * }
- * }
- * </pre>
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Allow test timers to be suspended, restarted or reset.
- * <tr><td> Allow tests to register multiple pass/fails and timings.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface TimingController
-{
- /**
- * Gets the timing controller associated with the current test thread. Tests that use timing controller should
- * always get the timing controller from this method in the same thread that called the setUp, tearDown or test
- * method. The controller returned by this method may be called from any thread because it remembers the thread
- * id of the original test thread.
- *
- * @return The timing controller associated with the current test thread.
- */
- public TimingController getControllerForCurrentThread();
-
- /**
- * Suspends the test timer.
- *
- * @return The current time in nanoseconds.
- */
- public long suspend();
-
- /**
- * Allows the test timer to continue running after a suspend.
- *
- * @return The current time in nanoseconds.
- */
- public long resume();
-
- /**
- * Completely restarts the test timer from zero.
- *
- * @return The current time in nanoseconds.
- */
- public long restart();
-
- /**
- * Register an additional pass/fail for the current test. The test result is assumed to apply to a test of
- * 'size' parmeter 1. Use the {@link #completeTest(boolean, int)} method to register timings with parameters.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed) throws InterruptedException;
-
- /**
- * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
- * 'size' parmeter.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- * @param param The test parameter size for parameterized tests.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed, int param) throws InterruptedException;
-
- /**
- * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
- * 'size' parmeter and allows the caller to sepecify the timing to log.
- *
- * @param testPassed Whether or not this timing is for a test pass or fail.
- * @param param The test parameter size for parameterized tests.
- * @param timeNanos The time in nano seconds to log the test result with.
- *
- * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
- * indicate to the test method that it should stop immediately.
- */
- public void completeTest(boolean testPassed, int param, long timeNanos) throws InterruptedException;
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * A TimingController is a interface that a test that is aware of the fact that it is being timed can use to manage
+ * the timer. Using this interface tests can suspend and resume test timers. This is usefull if you want to exclude
+ * some expensive preparation from being timed as part of a test. In general when timing tests to measure the
+ * performance of code, you should try to set up data in the #setUp where possible, or as static members in the test
+ * class. This is not always convenient, this interface gives you a way to suspend and resume, or event completely
+ * restart test timers, to get accurate measurements.
+ *
+ * <p/>The interface can also be used to register multiple test pass/fails and timings from a single test method.
+ * In some cases it is easier to write tests in this way. For example a concurrent and asynchronous test may make
+ * many asynchronous requests and then wait for replies to all its requests. Writing such a test with one send/reply
+ * per test method and trying to scale up using many threads will quickly run into limitations if more than about
+ * 100 asynchronous calls need to be made at once. A better way to write such a test is as a single method that sends
+ * many (perhaps thousands or millions) and waits for replies in two threads, one for send, one for replies. It can
+ * then log pass/fails and timings on each individual reply as they come back in, even though the test has been written
+ * to send thousands of requests per test method in order to do volume testing.
+ *
+ * <p/>If when the {@link #completeTest(boolean)} is called, the test runner decides that testing should stop (perhaps
+ * because a duration test has expired), it throws an InterruptedException to indicate that the test method should stop
+ * immediately. The test method can do this by allowing this exception to fall through, if no other clean-up handling
+ * is necessary, or it can simply return as soon as it possibly can. The test runner will still call the tearDown
+ * method in the usual way when this happens.
+ *
+ * <p/>Below are some examples of how this can be used. Not how checking that the timing controller is really available
+ * rather than assuming it is, means that the test can run as an ordinary JUnit test under the default test runners. In
+ * general code should be written to take advantage of the extended capabilities of junit toolkit, without assuming they
+ * are going to be run under its test runner.
+ *
+ * <pre>
+ * public class MyTest extends TestCase implements TimingControllerAware {
+ * ...
+ *
+ * timingUtils = this.getTimingController();
+ *
+ * // Do expensive data preparation here...
+ *
+ * if (timingUtils != null)
+ * timingUtils.restart();
+ * </pre>
+ *
+ * <pre>
+ * public class MyTest extends TestCase implements TimingControllerAware {
+ * ...
+ *
+ * public void myVolumeTest(int size) {
+ *
+ * timingUtils = this.getTimingController();
+ *
+ * boolean stopNow = false;
+ *
+ * // In Sender thread.
+ * for(int i = 0; !stopNow && i < size; i++)
+ * // Send request i.
+ * ...
+ *
+ * // In Receiver thread.
+ * onReceive(Object o) {
+ * try {
+ * // Check o is as expected.
+ * if (....)
+ * {
+ * if (timingUtils != null)
+ * timingUtils.completeTest(true);
+ * }
+ * else
+ * {
+ * if (timingUtils != null)
+ * timingUtils.completeTest(false);
+ * }
+ * } catch (InterruptedException e) {
+ * stopNow = true;
+ * return;
+ * }
+ * }
+ * </pre>
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Allow test timers to be suspended, restarted or reset.
+ * <tr><td> Allow tests to register multiple pass/fails and timings.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface TimingController
+{
+ /**
+ * Gets the timing controller associated with the current test thread. Tests that use timing controller should
+ * always get the timing controller from this method in the same thread that called the setUp, tearDown or test
+ * method. The controller returned by this method may be called from any thread because it remembers the thread
+ * id of the original test thread.
+ *
+ * @return The timing controller associated with the current test thread.
+ */
+ public TimingController getControllerForCurrentThread();
+
+ /**
+ * Suspends the test timer.
+ *
+ * @return The current time in nanoseconds.
+ */
+ public long suspend();
+
+ /**
+ * Allows the test timer to continue running after a suspend.
+ *
+ * @return The current time in nanoseconds.
+ */
+ public long resume();
+
+ /**
+ * Completely restarts the test timer from zero.
+ *
+ * @return The current time in nanoseconds.
+ */
+ public long restart();
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is assumed to apply to a test of
+ * 'size' parmeter 1. Use the {@link #completeTest(boolean, int)} method to register timings with parameters.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed) throws InterruptedException;
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
+ * 'size' parmeter.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ * @param param The test parameter size for parameterized tests.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed, int param) throws InterruptedException;
+
+ /**
+ * Register an additional pass/fail for the current test. The test result is applies to a test of the specified
+ * 'size' parmeter and allows the caller to sepecify the timing to log.
+ *
+ * @param testPassed Whether or not this timing is for a test pass or fail.
+ * @param param The test parameter size for parameterized tests.
+ * @param timeNanos The time in nano seconds to log the test result with.
+ *
+ * @throws InterruptedException If the test runner decides that testing should stop it throws this exception to
+ * indicate to the test method that it should stop immediately.
+ */
+ public void completeTest(boolean testPassed, int param, long timeNanos) throws InterruptedException;
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java
index 1ccdc7dbad..11db87e073 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/TimingControllerAware.java
@@ -1,43 +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.junit.extensions;
-
-/**
- * TimingControllerAware is an interface that tests that manipulate the timing controller should implement. It enables
- * the TK test runner to set the test up with a handle on the timing controller which the test can use to call back
- * to the test runner to manage the timers.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Provide timing controller insertion point for tests.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface TimingControllerAware
-{
- /**
- * Used by test runners that can supply a {@link TimingController} to set the controller on an aware test.
- *
- * @param controller The timing controller.
- */
- public void setTimingController(TimingController controller);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+/**
+ * TimingControllerAware is an interface that tests that manipulate the timing controller should implement. It enables
+ * the TK test runner to set the test up with a handle on the timing controller which the test can use to call back
+ * to the test runner to manage the timers.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide timing controller insertion point for tests.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface TimingControllerAware
+{
+ /**
+ * Used by test runners that can supply a {@link TimingController} to set the controller on an aware test.
+ *
+ * @param controller The timing controller.
+ */
+ public void setTimingController(TimingController controller);
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java
index 7a1e537b1c..d5690fc24a 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/WrappedSuiteTestDecorator.java
@@ -1,134 +1,134 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions;
-
-import junit.extensions.TestDecorator;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * WrappedSuiteTestDecorator is a test decorator that wraps a test suite, or another wrapped suite, but provides the
- * same functionality for the {@link junit.extensions.TestDecorator#countTestCases()} and {@link TestSuite#testAt(int)}
- * methods as the underlying suite. It returns the values that these methods provide, to enable classes using decorated
- * tests to drill down to the underlying tests in the suite. That is to say that it indexes and reports the number of
- * distinct tests in the suite, not the number of test runs that would result from, for example, wrapping the suite in a
- * repeating decorator.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Provide access to the underlying tests in a suite.
- * </table>
- *
- * @author Rupert Smith
- */
-public class WrappedSuiteTestDecorator extends TestDecorator
-{
- /** Used for logging. */
- private static Logger log = Logger.getLogger(WrappedSuiteTestDecorator.class);
-
- /** Holds the test suite that this supplies access to. */
- protected Test suite;
-
- /**
- * Creates a wrappred suite test decorator from a test suite.
- *
- * @param suite The test suite.
- */
- public WrappedSuiteTestDecorator(TestSuite suite)
- {
- super(suite);
- this.suite = suite;
- }
-
- /**
- * Creates a wrapped suite test decorator from another one.
- *
- * @param suite The test suite.
- */
- public WrappedSuiteTestDecorator(WrappedSuiteTestDecorator suite)
- {
- super(suite);
- this.suite = suite;
- }
-
- /**
- * Returns the test count of the wrapped suite.
- *
- * @return The test count of the wrapped suite.
- */
- public int countTestCases()
- {
- return suite.countTestCases();
- }
-
- /**
- * Gets the ith test from the test suite.
- *
- * @param i The index of the test within the suite to get.
- *
- * @return The test with the specified index.
- */
- public Test testAt(int i)
- {
- log.debug("public Test testAt(int i = " + i + "): called");
-
- if (suite instanceof WrappedSuiteTestDecorator)
- {
- return ((WrappedSuiteTestDecorator) suite).testAt(i);
- }
- else if (suite instanceof TestSuite)
- {
- return ((TestSuite) suite).testAt(i);
- }
-
- // This should never happen.
- return null;
- }
-
- /**
- * Gets all the tests from the underlying test suite.
- *
- * @return All the tests from the underlying test suite.
- */
- public Collection<Test> getAllUnderlyingTests()
- {
- log.debug("public Collection<Test> getAllUnderlyingTests(): called");
-
- List<Test> tests = new ArrayList<Test>();
-
- int numTests = countTestCases();
- log.debug("numTests = " + numTests);
-
- for (int i = 0; i < numTests; i++)
- {
- tests.add(testAt(i));
- }
-
- return tests;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions;
+
+import junit.extensions.TestDecorator;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * WrappedSuiteTestDecorator is a test decorator that wraps a test suite, or another wrapped suite, but provides the
+ * same functionality for the {@link junit.extensions.TestDecorator#countTestCases()} and {@link TestSuite#testAt(int)}
+ * methods as the underlying suite. It returns the values that these methods provide, to enable classes using decorated
+ * tests to drill down to the underlying tests in the suite. That is to say that it indexes and reports the number of
+ * distinct tests in the suite, not the number of test runs that would result from, for example, wrapping the suite in a
+ * repeating decorator.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide access to the underlying tests in a suite.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class WrappedSuiteTestDecorator extends TestDecorator
+{
+ /** Used for logging. */
+ private static Logger log = Logger.getLogger(WrappedSuiteTestDecorator.class);
+
+ /** Holds the test suite that this supplies access to. */
+ protected Test suite;
+
+ /**
+ * Creates a wrappred suite test decorator from a test suite.
+ *
+ * @param suite The test suite.
+ */
+ public WrappedSuiteTestDecorator(TestSuite suite)
+ {
+ super(suite);
+ this.suite = suite;
+ }
+
+ /**
+ * Creates a wrapped suite test decorator from another one.
+ *
+ * @param suite The test suite.
+ */
+ public WrappedSuiteTestDecorator(WrappedSuiteTestDecorator suite)
+ {
+ super(suite);
+ this.suite = suite;
+ }
+
+ /**
+ * Returns the test count of the wrapped suite.
+ *
+ * @return The test count of the wrapped suite.
+ */
+ public int countTestCases()
+ {
+ return suite.countTestCases();
+ }
+
+ /**
+ * Gets the ith test from the test suite.
+ *
+ * @param i The index of the test within the suite to get.
+ *
+ * @return The test with the specified index.
+ */
+ public Test testAt(int i)
+ {
+ log.debug("public Test testAt(int i = " + i + "): called");
+
+ if (suite instanceof WrappedSuiteTestDecorator)
+ {
+ return ((WrappedSuiteTestDecorator) suite).testAt(i);
+ }
+ else if (suite instanceof TestSuite)
+ {
+ return ((TestSuite) suite).testAt(i);
+ }
+
+ // This should never happen.
+ return null;
+ }
+
+ /**
+ * Gets all the tests from the underlying test suite.
+ *
+ * @return All the tests from the underlying test suite.
+ */
+ public Collection<Test> getAllUnderlyingTests()
+ {
+ log.debug("public Collection<Test> getAllUnderlyingTests(): called");
+
+ List<Test> tests = new ArrayList<Test>();
+
+ int numTests = countTestCases();
+ log.debug("numTests = " + numTests);
+
+ for (int i = 0; i < numTests; i++)
+ {
+ tests.add(testAt(i));
+ }
+
+ return tests;
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java
index a771e08cf7..f93212e0c5 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/CSVTestListener.java
@@ -1,532 +1,532 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.listeners;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestListener;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.ShutdownHookable;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * CSVTestListener is both a test listener, a timings listener, a memory listener and a parameter listener. It listens for test completion events and
- * then writes out all the data that it has listened to into a '.csv' (comma seperated values) file.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Listen to test events; start, end, fail, error.
- * <tr><td> Listen to test timings.
- * <tr><td> Listen to test memory usage.
- * <tr><td> Listen to parameterized test parameters.
- * <tr><td> Output all test data to a CSV file.
- * </table>
- *
- * @author Rupert Smith
- *
- * @todo Write an XML output class. Write a transform to convert it into an HTML page with timings as graphs.
- */
-public class CSVTestListener implements TestListener, TKTestListener, ShutdownHookable
-{
- /** Used for logging. */
- private static final Logger log = Logger.getLogger(CSVTestListener.class);
-
- /** The timings file writer. */
- private Writer timingsWriter;
-
- /**
- * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an
- * explicit thread id must be used, where notifications come from different threads than the ones that called
- * the test method.
- */
- Map<Long, TestResult> threadLocalResults = Collections.synchronizedMap(new HashMap<Long, TestResult>());
-
- /** Used to record the start time of a complete test run, for outputing statistics at the end of the test run. */
- private long batchStartTime;
-
- /** Used to record the number of errors accross a complete test run. */
- private int numError;
-
- /** Used to record the number of failures accross a complete test run. */
- private int numFailed;
-
- /** Used to record the number of passes accross a complete test run. */
- private int numPassed;
-
- /** Used to record the total tests run accross a complete test run. Always equal to passes + errors + fails. */
- private int totalTests;
-
- /** Used to recrod the current concurrency level for the test batch. */
- private int concurrencyLevel;
-
- /**
- * Used to record the total 'size' of the tests run, this is the number run times the average value of the test
- * size parameters.
- */
- private int totalSize;
-
- /**
- * Used to record the summation of all of the individual test timgings. Note that total time and summed time
- * are unlikely to be in agreement, exception for a single threaded test (with no setup time). Total time is
- * the time taken to run all the tests, summed time is the added up time that each individual test took. So if
- * two tests run in parallel and take one second each, total time will be one seconds, summed time will be two
- * seconds.
- */
- private long summedTime;
-
- /** Flag to indicate when batch has been started but not ended to ensure end batch stats are output only once. */
- private boolean batchStarted = false;
-
- /**
- * Creates a new CSVTestListener object.
- *
- * @param writer A writer where this CSV listener should write out its output to.
- */
- public CSVTestListener(Writer writer)
- {
- // log.debug("public CSVTestListener(Writer writer): called");
-
- // Keep the writer.
- this.timingsWriter = writer;
- }
-
- /**
- * Resets the test results to the default state of time zero, memory usage zero, test passed.
- *
- * @param test The test to resest any results for.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void reset(Test test, Long threadId)
- {
- // log.debug("public void reset(Test test = \"" + test + "\", Long threadId = " + threadId + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testTime = 0L;
- r.testStartMem = 0L;
- r.testEndMem = 0L;
- r.testState = "Pass";
- r.testParam = 0;
- }
-
- /**
- * Called when a test results in an error.
- *
- * @param test The test which is in error.
- * @param t Any Throwable raised by the test in error.
- */
- public void addError(Test test, Throwable t)
- {
- // log.debug("public void addError(Test test, Throwable t): called");
-
- TestResult r = threadLocalResults.get(Thread.currentThread().getId());
- r.testState = "Error";
- }
-
- /**
- * Called when a test results in a failure.
- *
- * @param test The test which failed.
- * @param t The AssertionFailedError that encapsulates the test failure.
- */
- public void addFailure(Test test, AssertionFailedError t)
- {
- // log.debug("public void addFailure(Test \"" + test + "\", AssertionFailedError t): called");
-
- TestResult r = threadLocalResults.get(Thread.currentThread().getId());
- r.testState = "Failure";
- }
-
- /**
- * Called when a test completes to mark it as a test fail. This method should be used when registering a
- * failure from a different thread than the one that started the test.
- *
- * @param test The test which failed.
- * @param e The assertion that failed the test.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void addFailure(Test test, AssertionFailedError e, Long threadId)
- {
- // log.debug("public void addFailure(Test test = \"" + test + "\", AssertionFailedError e, Long threadId = " + threadId
- // + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testState = "Failure";
- }
-
- /**
- * Called when a test completes. Success, failure and errors.
- *
- * @param test The test which completed.
- */
- public void endTest(Test test)
- {
- // log.debug("public void endTest(Test \"" + test + "\"): called");
-
- TestResult r = threadLocalResults.get(Thread.currentThread().getId());
-
- writeTestResults(r, test);
-
- // Clear all the test results for the thread.
- threadLocalResults.remove(Thread.currentThread().getId());
- }
-
- /**
- * Called when a test starts.
- *
- * @param test The test wich has started.
- */
- public void startTest(Test test)
- {
- // log.debug("public void startTest(Test \"" + test + "\"): called");
-
- // Initialize the thread local test results.
- threadLocalResults.put(Thread.currentThread().getId(), new TestResult());
- }
-
- /**
- * Should be called every time a test completes with the run time of that test.
- *
- * @param test The name of the test.
- * @param nanos The run time of the test in nanoseconds.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void timing(Test test, long nanos, Long threadId)
- {
- // log.debug("public void timing(String \"" + test + "\", long " + nanos + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testTime = nanos;
- summedTime += nanos;
- }
-
- /**
- * Should be called every time a test completed with the amount of memory used before and after the test was run.
- *
- * @param test The test which memory was measured for.
- * @param memStart The total JVM memory used before the test was run.
- * @param memEnd The total JVM memory used after the test was run.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
- {
- // log.debug("public void memoryUsed(Test \"" + test + "\", long " + memStart + ", long " + memEnd + ", Long "
- // + threadId + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testStartMem = memStart;
- r.testEndMem = memEnd;
- }
-
- /**
- * Should be called every time a parameterized test completed with the int value of its test parameter.
- *
- * @param test The test which memory was measured for.
- * @param parameter The int parameter value.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void parameterValue(Test test, int parameter, Long threadId)
- {
- // log.debug("public void parameterValue(Test test = \"" + test + "\", int parameter = " + parameter + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testParam = parameter;
- totalSize += parameter;
- }
-
- /**
- * Should be called every time a test completes with the current number of test threads running. This should not
- * change within a test batch, therefore it is safe to take this as a batch level property value too.
- *
- * @param test The test for which the measurement is being generated.
- * @param threads The number of tests being run concurrently.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void concurrencyLevel(Test test, int threads, Long threadId)
- {
- // log.debug("public void concurrencyLevel(Test test = \"" + test + "\", int threads = " + threads + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.testConcurrency = threads;
- concurrencyLevel = threads;
-
- }
-
- /**
- * Called when a test completes. Success, failure and errors. This method should be used when registering an
- * end test from a different thread than the one that started the test.
- *
- * @param test The test which completed.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void endTest(Test test, Long threadId)
- {
- // log.debug("public void endTest(Test test = \"" + test + "\", Long threadId " + threadId + "): called");
-
- TestResult r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- writeTestResults(r, test);
- }
-
- /**
- * Takes a time stamp for the beginning of the batch and resets stats counted for the batch.
- */
- public synchronized void startBatch()
- {
- numError = 0;
- numFailed = 0;
- numPassed = 0;
- totalTests = 0;
- totalSize = 0;
- batchStartTime = System.nanoTime();
- summedTime = 0;
- batchStarted = true;
-
- // Write out the column headers for the batch.
- writeColumnHeaders();
- }
-
- /**
- * Takes a time stamp for the end of the batch to calculate the total run time.
- * Write this and other stats out to the tail of the csv file.
- *
- * @param parameters The optional test parameters, may be null.
- */
- public synchronized void endBatch(Properties parameters)
- {
- boolean noParams = (parameters == null) || (parameters.size() == 0);
-
- // Check that a batch has been started but not ended.
- if (batchStarted)
- {
- long batchEndTime = System.nanoTime();
- float totalTimeMillis = ((float) (batchEndTime - batchStartTime)) / 1000000f;
- float summedTimeMillis = ((float) summedTime) / 1000000f;
-
- // Write the stats for the batch out.
- try
- {
- synchronized (this.getClass())
- {
- timingsWriter.write("Total Tests:, " + totalTests + ", ");
- timingsWriter.write("Total Passed:, " + numPassed + ", ");
- timingsWriter.write("Total Failed:, " + numFailed + ", ");
- timingsWriter.write("Total Error:, " + numError + ", ");
- timingsWriter.write("Total Size:, " + totalSize + ", ");
- timingsWriter.write("Summed Time:, " + summedTimeMillis + ", ");
- timingsWriter.write("Concurrency Level:, " + concurrencyLevel + ", ");
- timingsWriter.write("Total Time:, " + totalTimeMillis + ", ");
- timingsWriter.write("Test Throughput:, " + (((float) totalTests) / totalTimeMillis) + ", ");
- timingsWriter.write("Test * Size Throughput:, " + (((float) totalSize) / totalTimeMillis)
- + (noParams ? "\n\n" : ", "));
-
- // Write out the test parameters if there are any specified.
- if (!noParams)
- {
- properties(parameters);
- }
-
- timingsWriter.flush();
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write out end batch statistics: " + e, e);
- }
- }
-
- // Reset the batch started flag to ensure stats are only output once.
- batchStarted = false;
- }
-
- /**
- * Notifies listeners of the tests read/set properties.
- *
- * @param properties The tests read/set properties.
- */
- public void properties(Properties properties)
- {
- // log.debug("public void properties(Properties properties): called");
-
- // Write the properties out to the results file.
- try
- {
- synchronized (this.getClass())
- {
- Set keySet = new TreeSet(properties.keySet());
-
- // timingsWriter.write("\n");
-
- for (Object key : keySet)
- {
- timingsWriter.write(key + " = , " + properties.getProperty((String) key) + ", ");
- }
-
- timingsWriter.write("\n\n");
- // timingsWriter.flush();
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write out test parameters: " + e, e);
- }
-
- // Write out the column headers after the properties.
- // writeColumnHeaders();
- }
-
- /**
- * Writes out and flushes the column headers for raw test data.
- */
- private void writeColumnHeaders()
- {
- // Write the column headers for the CSV file. Any IO exceptions are ignored.
- try
- {
- timingsWriter.write("Class, ");
- timingsWriter.write("Method, ");
- timingsWriter.write("Thread, ");
- timingsWriter.write("Test Outcome, ");
- timingsWriter.write("Time (milliseconds), ");
- timingsWriter.write("Memory Used (bytes), ");
- timingsWriter.write("Concurrency level, ");
- timingsWriter.write("Test Size\n");
-
- timingsWriter.flush();
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write out column headers: " + e, e);
- }
- }
-
- /**
- * Writes out the test results for the specified test. This outputs a single line of results to the csv file.
- *
- * @param r The test results to write out.
- * @param test The test to write them out for.
- */
- private void writeTestResults(TestResult r, Test test)
- {
- // Update the running stats for this batch.
- if ("Error".equals(r.testState))
- {
- numError++;
- }
- else if ("Failure".equals(r.testState))
- {
- numFailed++;
- }
- else if ("Pass".equals(r.testState))
- {
- numPassed++;
- }
-
- totalTests++;
-
- // Write the test name and thread information plus all instrumenation a line of the CSV ouput. Any IO
- // exceptions are ignored.
- try
- {
- synchronized (this.getClass())
- {
- timingsWriter.write(test.getClass().getName() + ", ");
- timingsWriter.write(((test instanceof TestCase) ? ((TestCase) test).getName() : "") + ", ");
- timingsWriter.write(Thread.currentThread().getName() + ", ");
- timingsWriter.write(r.testState + ", ");
- timingsWriter.write((((float) r.testTime) / 1000000f) + ", ");
- timingsWriter.write((r.testEndMem - r.testStartMem) + ", ");
- timingsWriter.write(r.testConcurrency + ", ");
- timingsWriter.write(r.testParam + "\n");
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write out test results: " + e, e);
- }
- }
-
- /**
- * Supplies the shutdown hook. This attempts to flush the results in the event of the test runner being prematurely
- * suspended before the end of the current test batch.
- *
- * @return The shut down hook.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- log.debug("CSVTestListener::ShutdownHook: called");
-
- // Complete the current test batch stats.
- endBatch(TestContextProperties.getInstance());
- }
- });
- }
-
- /** Captures test results packaged into a single object, so that it can be set up as a thread local. */
- private static class TestResult
- {
- /** Used to hold the test timing. */
- public long testTime;
-
- /** Used to hold the test start memory usage. */
- public long testStartMem;
-
- /** Used to hold the test end memory usage. */
- public long testEndMem;
-
- /** Used to hold the test pass/fail/error state. */
- public String testState = "Pass";
-
- /** Used to hold the test parameter value. */
- public int testParam;
-
- /** Used to hold the concurrency level under which the test was run. */
- public int testConcurrency;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.listeners;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.ShutdownHookable;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * CSVTestListener is both a test listener, a timings listener, a memory listener and a parameter listener. It listens for test completion events and
+ * then writes out all the data that it has listened to into a '.csv' (comma seperated values) file.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Listen to test events; start, end, fail, error.
+ * <tr><td> Listen to test timings.
+ * <tr><td> Listen to test memory usage.
+ * <tr><td> Listen to parameterized test parameters.
+ * <tr><td> Output all test data to a CSV file.
+ * </table>
+ *
+ * @author Rupert Smith
+ *
+ * @todo Write an XML output class. Write a transform to convert it into an HTML page with timings as graphs.
+ */
+public class CSVTestListener implements TestListener, TKTestListener, ShutdownHookable
+{
+ /** Used for logging. */
+ private static final Logger log = Logger.getLogger(CSVTestListener.class);
+
+ /** The timings file writer. */
+ private Writer timingsWriter;
+
+ /**
+ * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an
+ * explicit thread id must be used, where notifications come from different threads than the ones that called
+ * the test method.
+ */
+ Map<Long, TestResult> threadLocalResults = Collections.synchronizedMap(new HashMap<Long, TestResult>());
+
+ /** Used to record the start time of a complete test run, for outputing statistics at the end of the test run. */
+ private long batchStartTime;
+
+ /** Used to record the number of errors accross a complete test run. */
+ private int numError;
+
+ /** Used to record the number of failures accross a complete test run. */
+ private int numFailed;
+
+ /** Used to record the number of passes accross a complete test run. */
+ private int numPassed;
+
+ /** Used to record the total tests run accross a complete test run. Always equal to passes + errors + fails. */
+ private int totalTests;
+
+ /** Used to recrod the current concurrency level for the test batch. */
+ private int concurrencyLevel;
+
+ /**
+ * Used to record the total 'size' of the tests run, this is the number run times the average value of the test
+ * size parameters.
+ */
+ private int totalSize;
+
+ /**
+ * Used to record the summation of all of the individual test timgings. Note that total time and summed time
+ * are unlikely to be in agreement, exception for a single threaded test (with no setup time). Total time is
+ * the time taken to run all the tests, summed time is the added up time that each individual test took. So if
+ * two tests run in parallel and take one second each, total time will be one seconds, summed time will be two
+ * seconds.
+ */
+ private long summedTime;
+
+ /** Flag to indicate when batch has been started but not ended to ensure end batch stats are output only once. */
+ private boolean batchStarted = false;
+
+ /**
+ * Creates a new CSVTestListener object.
+ *
+ * @param writer A writer where this CSV listener should write out its output to.
+ */
+ public CSVTestListener(Writer writer)
+ {
+ // log.debug("public CSVTestListener(Writer writer): called");
+
+ // Keep the writer.
+ this.timingsWriter = writer;
+ }
+
+ /**
+ * Resets the test results to the default state of time zero, memory usage zero, test passed.
+ *
+ * @param test The test to resest any results for.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void reset(Test test, Long threadId)
+ {
+ // log.debug("public void reset(Test test = \"" + test + "\", Long threadId = " + threadId + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testTime = 0L;
+ r.testStartMem = 0L;
+ r.testEndMem = 0L;
+ r.testState = "Pass";
+ r.testParam = 0;
+ }
+
+ /**
+ * Called when a test results in an error.
+ *
+ * @param test The test which is in error.
+ * @param t Any Throwable raised by the test in error.
+ */
+ public void addError(Test test, Throwable t)
+ {
+ // log.debug("public void addError(Test test, Throwable t): called");
+
+ TestResult r = threadLocalResults.get(Thread.currentThread().getId());
+ r.testState = "Error";
+ }
+
+ /**
+ * Called when a test results in a failure.
+ *
+ * @param test The test which failed.
+ * @param t The AssertionFailedError that encapsulates the test failure.
+ */
+ public void addFailure(Test test, AssertionFailedError t)
+ {
+ // log.debug("public void addFailure(Test \"" + test + "\", AssertionFailedError t): called");
+
+ TestResult r = threadLocalResults.get(Thread.currentThread().getId());
+ r.testState = "Failure";
+ }
+
+ /**
+ * Called when a test completes to mark it as a test fail. This method should be used when registering a
+ * failure from a different thread than the one that started the test.
+ *
+ * @param test The test which failed.
+ * @param e The assertion that failed the test.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void addFailure(Test test, AssertionFailedError e, Long threadId)
+ {
+ // log.debug("public void addFailure(Test test = \"" + test + "\", AssertionFailedError e, Long threadId = " + threadId
+ // + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testState = "Failure";
+ }
+
+ /**
+ * Called when a test completes. Success, failure and errors.
+ *
+ * @param test The test which completed.
+ */
+ public void endTest(Test test)
+ {
+ // log.debug("public void endTest(Test \"" + test + "\"): called");
+
+ TestResult r = threadLocalResults.get(Thread.currentThread().getId());
+
+ writeTestResults(r, test);
+
+ // Clear all the test results for the thread.
+ threadLocalResults.remove(Thread.currentThread().getId());
+ }
+
+ /**
+ * Called when a test starts.
+ *
+ * @param test The test wich has started.
+ */
+ public void startTest(Test test)
+ {
+ // log.debug("public void startTest(Test \"" + test + "\"): called");
+
+ // Initialize the thread local test results.
+ threadLocalResults.put(Thread.currentThread().getId(), new TestResult());
+ }
+
+ /**
+ * Should be called every time a test completes with the run time of that test.
+ *
+ * @param test The name of the test.
+ * @param nanos The run time of the test in nanoseconds.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void timing(Test test, long nanos, Long threadId)
+ {
+ // log.debug("public void timing(String \"" + test + "\", long " + nanos + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testTime = nanos;
+ summedTime += nanos;
+ }
+
+ /**
+ * Should be called every time a test completed with the amount of memory used before and after the test was run.
+ *
+ * @param test The test which memory was measured for.
+ * @param memStart The total JVM memory used before the test was run.
+ * @param memEnd The total JVM memory used after the test was run.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
+ {
+ // log.debug("public void memoryUsed(Test \"" + test + "\", long " + memStart + ", long " + memEnd + ", Long "
+ // + threadId + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testStartMem = memStart;
+ r.testEndMem = memEnd;
+ }
+
+ /**
+ * Should be called every time a parameterized test completed with the int value of its test parameter.
+ *
+ * @param test The test which memory was measured for.
+ * @param parameter The int parameter value.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void parameterValue(Test test, int parameter, Long threadId)
+ {
+ // log.debug("public void parameterValue(Test test = \"" + test + "\", int parameter = " + parameter + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testParam = parameter;
+ totalSize += parameter;
+ }
+
+ /**
+ * Should be called every time a test completes with the current number of test threads running. This should not
+ * change within a test batch, therefore it is safe to take this as a batch level property value too.
+ *
+ * @param test The test for which the measurement is being generated.
+ * @param threads The number of tests being run concurrently.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void concurrencyLevel(Test test, int threads, Long threadId)
+ {
+ // log.debug("public void concurrencyLevel(Test test = \"" + test + "\", int threads = " + threads + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.testConcurrency = threads;
+ concurrencyLevel = threads;
+
+ }
+
+ /**
+ * Called when a test completes. Success, failure and errors. This method should be used when registering an
+ * end test from a different thread than the one that started the test.
+ *
+ * @param test The test which completed.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void endTest(Test test, Long threadId)
+ {
+ // log.debug("public void endTest(Test test = \"" + test + "\", Long threadId " + threadId + "): called");
+
+ TestResult r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ writeTestResults(r, test);
+ }
+
+ /**
+ * Takes a time stamp for the beginning of the batch and resets stats counted for the batch.
+ */
+ public synchronized void startBatch()
+ {
+ numError = 0;
+ numFailed = 0;
+ numPassed = 0;
+ totalTests = 0;
+ totalSize = 0;
+ batchStartTime = System.nanoTime();
+ summedTime = 0;
+ batchStarted = true;
+
+ // Write out the column headers for the batch.
+ writeColumnHeaders();
+ }
+
+ /**
+ * Takes a time stamp for the end of the batch to calculate the total run time.
+ * Write this and other stats out to the tail of the csv file.
+ *
+ * @param parameters The optional test parameters, may be null.
+ */
+ public synchronized void endBatch(Properties parameters)
+ {
+ boolean noParams = (parameters == null) || (parameters.size() == 0);
+
+ // Check that a batch has been started but not ended.
+ if (batchStarted)
+ {
+ long batchEndTime = System.nanoTime();
+ float totalTimeMillis = ((float) (batchEndTime - batchStartTime)) / 1000000f;
+ float summedTimeMillis = ((float) summedTime) / 1000000f;
+
+ // Write the stats for the batch out.
+ try
+ {
+ synchronized (this.getClass())
+ {
+ timingsWriter.write("Total Tests:, " + totalTests + ", ");
+ timingsWriter.write("Total Passed:, " + numPassed + ", ");
+ timingsWriter.write("Total Failed:, " + numFailed + ", ");
+ timingsWriter.write("Total Error:, " + numError + ", ");
+ timingsWriter.write("Total Size:, " + totalSize + ", ");
+ timingsWriter.write("Summed Time:, " + summedTimeMillis + ", ");
+ timingsWriter.write("Concurrency Level:, " + concurrencyLevel + ", ");
+ timingsWriter.write("Total Time:, " + totalTimeMillis + ", ");
+ timingsWriter.write("Test Throughput:, " + (((float) totalTests) / totalTimeMillis) + ", ");
+ timingsWriter.write("Test * Size Throughput:, " + (((float) totalSize) / totalTimeMillis)
+ + (noParams ? "\n\n" : ", "));
+
+ // Write out the test parameters if there are any specified.
+ if (!noParams)
+ {
+ properties(parameters);
+ }
+
+ timingsWriter.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write out end batch statistics: " + e, e);
+ }
+ }
+
+ // Reset the batch started flag to ensure stats are only output once.
+ batchStarted = false;
+ }
+
+ /**
+ * Notifies listeners of the tests read/set properties.
+ *
+ * @param properties The tests read/set properties.
+ */
+ public void properties(Properties properties)
+ {
+ // log.debug("public void properties(Properties properties): called");
+
+ // Write the properties out to the results file.
+ try
+ {
+ synchronized (this.getClass())
+ {
+ Set keySet = new TreeSet(properties.keySet());
+
+ // timingsWriter.write("\n");
+
+ for (Object key : keySet)
+ {
+ timingsWriter.write(key + " = , " + properties.getProperty((String) key) + ", ");
+ }
+
+ timingsWriter.write("\n\n");
+ // timingsWriter.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write out test parameters: " + e, e);
+ }
+
+ // Write out the column headers after the properties.
+ // writeColumnHeaders();
+ }
+
+ /**
+ * Writes out and flushes the column headers for raw test data.
+ */
+ private void writeColumnHeaders()
+ {
+ // Write the column headers for the CSV file. Any IO exceptions are ignored.
+ try
+ {
+ timingsWriter.write("Class, ");
+ timingsWriter.write("Method, ");
+ timingsWriter.write("Thread, ");
+ timingsWriter.write("Test Outcome, ");
+ timingsWriter.write("Time (milliseconds), ");
+ timingsWriter.write("Memory Used (bytes), ");
+ timingsWriter.write("Concurrency level, ");
+ timingsWriter.write("Test Size\n");
+
+ timingsWriter.flush();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write out column headers: " + e, e);
+ }
+ }
+
+ /**
+ * Writes out the test results for the specified test. This outputs a single line of results to the csv file.
+ *
+ * @param r The test results to write out.
+ * @param test The test to write them out for.
+ */
+ private void writeTestResults(TestResult r, Test test)
+ {
+ // Update the running stats for this batch.
+ if ("Error".equals(r.testState))
+ {
+ numError++;
+ }
+ else if ("Failure".equals(r.testState))
+ {
+ numFailed++;
+ }
+ else if ("Pass".equals(r.testState))
+ {
+ numPassed++;
+ }
+
+ totalTests++;
+
+ // Write the test name and thread information plus all instrumenation a line of the CSV ouput. Any IO
+ // exceptions are ignored.
+ try
+ {
+ synchronized (this.getClass())
+ {
+ timingsWriter.write(test.getClass().getName() + ", ");
+ timingsWriter.write(((test instanceof TestCase) ? ((TestCase) test).getName() : "") + ", ");
+ timingsWriter.write(Thread.currentThread().getName() + ", ");
+ timingsWriter.write(r.testState + ", ");
+ timingsWriter.write((((float) r.testTime) / 1000000f) + ", ");
+ timingsWriter.write((r.testEndMem - r.testStartMem) + ", ");
+ timingsWriter.write(r.testConcurrency + ", ");
+ timingsWriter.write(r.testParam + "\n");
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write out test results: " + e, e);
+ }
+ }
+
+ /**
+ * Supplies the shutdown hook. This attempts to flush the results in the event of the test runner being prematurely
+ * suspended before the end of the current test batch.
+ *
+ * @return The shut down hook.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ log.debug("CSVTestListener::ShutdownHook: called");
+
+ // Complete the current test batch stats.
+ endBatch(TestContextProperties.getInstance());
+ }
+ });
+ }
+
+ /** Captures test results packaged into a single object, so that it can be set up as a thread local. */
+ private static class TestResult
+ {
+ /** Used to hold the test timing. */
+ public long testTime;
+
+ /** Used to hold the test start memory usage. */
+ public long testStartMem;
+
+ /** Used to hold the test end memory usage. */
+ public long testEndMem;
+
+ /** Used to hold the test pass/fail/error state. */
+ public String testState = "Pass";
+
+ /** Used to hold the test parameter value. */
+ public int testParam;
+
+ /** Used to hold the concurrency level under which the test was run. */
+ public int testConcurrency;
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java
index 5c328a8814..2955fba2bd 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/ConsoleTestListener.java
@@ -1,264 +1,264 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.listeners;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestListener;
-
-import org.apache.qpid.junit.extensions.SleepThrottle;
-import org.apache.qpid.junit.extensions.Throttle;
-
-import java.util.Properties;
-
-/**
- * ConsoleTestListener provides feedback to the console, as test timings are taken, by drawing a '.', or an 'E', or an
- * 'F', for each test that passes, is in error or fails. It does this for every test result registered with the framework,
- * not just on the completion of each test method as the JUnit one does. It also uses a throttle to cap the rate of
- * dot drawing, as exessively high rates can degrade test performance without providing much usefull feedback to the user.
- * Unlike the JUnit dot drawing feedback, this one will correctly wrap lines when tests are run concurrently (the
- * rate capping ensures that this does not become a hot-spot for thread contention).
- *
- * <p/>Where rate capping causes the conflation of multiple requested dots into a single dot, the dot that is actually
- * drawn will be the worst result within the conflation period, that is, error is worse than fail which is worse than pass.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Draw dots as each test result completes, at a capped rate.
- * </table>
- *
- * @author Rupert Smith
- */
-public class ConsoleTestListener implements TestListener, TKTestListener
-{
- /** Used to indicate a test pass. */
- private static final int PASS = 1;
-
- /** Used to indicate a test failure. */
- private static final int FAIL = 2;
-
- /** Used to indicate a test error. */
- private static final int ERROR = 3;
-
- /** Defines the maximum number of columns of dots to print. */
- private static final int MAX_COLUMNS = 80;
-
- /** Used to throttle the dot writing rate. */
- Throttle throttle;
-
- /** Tracks the worst test result so far, when the throttled print method must conflate results due to throttling. */
- private int conflatedResult = 0;
-
- /** Tracks the column count as dots are printed, so that newlines can be inserted at the right margin. */
- private int columnCount = 0;
-
- /** Used as a monitor on the print method criticial section, to ensure that line ends always happen in the right place. */
- private final Object printMonitor = new Object();
-
- /**
- * Creates a dot drawing feedback test listener, set by default to 80 columns at 80 dots per second capped rate.
- */
- public ConsoleTestListener()
- {
- throttle = new SleepThrottle();
- throttle.setRate(80f);
- }
-
- /**
- * Prints dots at a capped rate, conflating the requested type of dot to draw if this method is called at a rate
- * higher than the capped rate. The conflation works by always printing the worst result that occurs within the
- * conflation period, that is, error is worse than fail which is worse than a pass.
- *
- * @param result The type of dot to draw, {@link #PASS}, {@link #FAIL} or {@link #ERROR}.
- */
- private void throttledPrint(int result)
- {
- conflatedResult = (result > conflatedResult) ? result : conflatedResult;
-
- if (throttle.checkThrottle())
- {
- synchronized (printMonitor)
- {
- switch (conflatedResult)
- {
- default:
- case PASS:
- System.out.print('.');
- break;
-
- case FAIL:
- System.out.print('F');
- break;
-
- case ERROR:
- System.out.print('E');
- break;
- }
-
- columnCount = (columnCount >= MAX_COLUMNS) ? 0 : (columnCount + 1);
-
- if (columnCount == 0)
- {
- System.out.print('\n');
- }
-
- conflatedResult = 0;
- }
- }
- }
-
- /**
- * An error occurred.
- *
- * @param test The test in error. Ignored.
- * @param t The error that the test threw. Ignored.
- */
- public void addError(Test test, Throwable t)
- {
- throttledPrint(ERROR);
- }
-
- /**
- * A failure occurred.
- *
- * @param test The test that failed. Ignored.
- * @param t The assertion failure that the test threw. Ignored.
- */
- public void addFailure(Test test, AssertionFailedError t)
- {
- throttledPrint(FAIL);
- }
-
- /**
- * A test ended.
- *
- * @param test The test that ended. Ignored.
- */
- public void endTest(Test test)
- {
- throttledPrint(PASS);
- }
-
- /**
- * A test started.
- *
- * @param test The test that started. Ignored.
- */
- public void startTest(Test test)
- { }
-
- /**
- * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
- *
- * @param test The test to resest any results for.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void reset(Test test, Long threadId)
- { }
-
- /**
- * Should be called every time a test completes with the run time of that test.
- *
- * @param test The name of the test.
- * @param nanos The run time of the test in nanoseconds.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void timing(Test test, long nanos, Long threadId)
- { }
-
- /**
- * Should be called every time a test completed with the amount of memory used before and after the test was run.
- *
- * @param test The test which memory was measured for.
- * @param memStart The total JVM memory used before the test was run.
- * @param memEnd The total JVM memory used after the test was run.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
- { }
-
- /**
- * Should be called every time a parameterized test completed with the int value of its test parameter.
- *
- * @param test The test which memory was measured for.
- * @param parameter The int parameter value.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void parameterValue(Test test, int parameter, Long threadId)
- { }
-
- /**
- * Should be called every time a test completes with the current number of test threads running.
- *
- * @param test The test for which the measurement is being generated.
- * @param threads The number of tests being run concurrently.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void concurrencyLevel(Test test, int threads, Long threadId)
- { }
-
- /**
- * Called when a test completes. Success, failure and errors. This method should be used when registering an
- * end test from a different thread than the one that started the test.
- *
- * @param test The test which completed.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void endTest(Test test, Long threadId)
- {
- throttledPrint(PASS);
- }
-
- /**
- * Called when a test completes to mark it as a test fail. This method should be used when registering a
- * failure from a different thread than the one that started the test.
- *
- * @param test The test which failed.
- * @param e The assertion that failed the test.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void addFailure(Test test, AssertionFailedError e, Long threadId)
- {
- throttledPrint(FAIL);
- }
-
- /**
- * Notifies listeners of the start of a complete run of tests.
- */
- public void startBatch()
- { }
-
- /**
- * Notifies listeners of the end of a complete run of tests.
- *
- * @param parameters The optional test parameters to log out with the batch results.
- */
- public void endBatch(Properties parameters)
- { }
-
- /**
- * Notifies listeners of the tests read/set properties.
- *
- * @param properties The tests read/set properties.
- */
- public void properties(Properties properties)
- { }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.listeners;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+
+import org.apache.qpid.junit.extensions.SleepThrottle;
+import org.apache.qpid.junit.extensions.Throttle;
+
+import java.util.Properties;
+
+/**
+ * ConsoleTestListener provides feedback to the console, as test timings are taken, by drawing a '.', or an 'E', or an
+ * 'F', for each test that passes, is in error or fails. It does this for every test result registered with the framework,
+ * not just on the completion of each test method as the JUnit one does. It also uses a throttle to cap the rate of
+ * dot drawing, as exessively high rates can degrade test performance without providing much usefull feedback to the user.
+ * Unlike the JUnit dot drawing feedback, this one will correctly wrap lines when tests are run concurrently (the
+ * rate capping ensures that this does not become a hot-spot for thread contention).
+ *
+ * <p/>Where rate capping causes the conflation of multiple requested dots into a single dot, the dot that is actually
+ * drawn will be the worst result within the conflation period, that is, error is worse than fail which is worse than pass.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Draw dots as each test result completes, at a capped rate.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ConsoleTestListener implements TestListener, TKTestListener
+{
+ /** Used to indicate a test pass. */
+ private static final int PASS = 1;
+
+ /** Used to indicate a test failure. */
+ private static final int FAIL = 2;
+
+ /** Used to indicate a test error. */
+ private static final int ERROR = 3;
+
+ /** Defines the maximum number of columns of dots to print. */
+ private static final int MAX_COLUMNS = 80;
+
+ /** Used to throttle the dot writing rate. */
+ Throttle throttle;
+
+ /** Tracks the worst test result so far, when the throttled print method must conflate results due to throttling. */
+ private int conflatedResult = 0;
+
+ /** Tracks the column count as dots are printed, so that newlines can be inserted at the right margin. */
+ private int columnCount = 0;
+
+ /** Used as a monitor on the print method criticial section, to ensure that line ends always happen in the right place. */
+ private final Object printMonitor = new Object();
+
+ /**
+ * Creates a dot drawing feedback test listener, set by default to 80 columns at 80 dots per second capped rate.
+ */
+ public ConsoleTestListener()
+ {
+ throttle = new SleepThrottle();
+ throttle.setRate(80f);
+ }
+
+ /**
+ * Prints dots at a capped rate, conflating the requested type of dot to draw if this method is called at a rate
+ * higher than the capped rate. The conflation works by always printing the worst result that occurs within the
+ * conflation period, that is, error is worse than fail which is worse than a pass.
+ *
+ * @param result The type of dot to draw, {@link #PASS}, {@link #FAIL} or {@link #ERROR}.
+ */
+ private void throttledPrint(int result)
+ {
+ conflatedResult = (result > conflatedResult) ? result : conflatedResult;
+
+ if (throttle.checkThrottle())
+ {
+ synchronized (printMonitor)
+ {
+ switch (conflatedResult)
+ {
+ default:
+ case PASS:
+ System.out.print('.');
+ break;
+
+ case FAIL:
+ System.out.print('F');
+ break;
+
+ case ERROR:
+ System.out.print('E');
+ break;
+ }
+
+ columnCount = (columnCount >= MAX_COLUMNS) ? 0 : (columnCount + 1);
+
+ if (columnCount == 0)
+ {
+ System.out.print('\n');
+ }
+
+ conflatedResult = 0;
+ }
+ }
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param test The test in error. Ignored.
+ * @param t The error that the test threw. Ignored.
+ */
+ public void addError(Test test, Throwable t)
+ {
+ throttledPrint(ERROR);
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param test The test that failed. Ignored.
+ * @param t The assertion failure that the test threw. Ignored.
+ */
+ public void addFailure(Test test, AssertionFailedError t)
+ {
+ throttledPrint(FAIL);
+ }
+
+ /**
+ * A test ended.
+ *
+ * @param test The test that ended. Ignored.
+ */
+ public void endTest(Test test)
+ {
+ throttledPrint(PASS);
+ }
+
+ /**
+ * A test started.
+ *
+ * @param test The test that started. Ignored.
+ */
+ public void startTest(Test test)
+ { }
+
+ /**
+ * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
+ *
+ * @param test The test to resest any results for.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void reset(Test test, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a test completes with the run time of that test.
+ *
+ * @param test The name of the test.
+ * @param nanos The run time of the test in nanoseconds.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void timing(Test test, long nanos, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a test completed with the amount of memory used before and after the test was run.
+ *
+ * @param test The test which memory was measured for.
+ * @param memStart The total JVM memory used before the test was run.
+ * @param memEnd The total JVM memory used after the test was run.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a parameterized test completed with the int value of its test parameter.
+ *
+ * @param test The test which memory was measured for.
+ * @param parameter The int parameter value.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void parameterValue(Test test, int parameter, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a test completes with the current number of test threads running.
+ *
+ * @param test The test for which the measurement is being generated.
+ * @param threads The number of tests being run concurrently.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void concurrencyLevel(Test test, int threads, Long threadId)
+ { }
+
+ /**
+ * Called when a test completes. Success, failure and errors. This method should be used when registering an
+ * end test from a different thread than the one that started the test.
+ *
+ * @param test The test which completed.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void endTest(Test test, Long threadId)
+ {
+ throttledPrint(PASS);
+ }
+
+ /**
+ * Called when a test completes to mark it as a test fail. This method should be used when registering a
+ * failure from a different thread than the one that started the test.
+ *
+ * @param test The test which failed.
+ * @param e The assertion that failed the test.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void addFailure(Test test, AssertionFailedError e, Long threadId)
+ {
+ throttledPrint(FAIL);
+ }
+
+ /**
+ * Notifies listeners of the start of a complete run of tests.
+ */
+ public void startBatch()
+ { }
+
+ /**
+ * Notifies listeners of the end of a complete run of tests.
+ *
+ * @param parameters The optional test parameters to log out with the batch results.
+ */
+ public void endBatch(Properties parameters)
+ { }
+
+ /**
+ * Notifies listeners of the tests read/set properties.
+ *
+ * @param properties The tests read/set properties.
+ */
+ public void properties(Properties properties)
+ { }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java
index 4f08e8bf2d..11fc6a7451 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/TKTestListener.java
@@ -1,132 +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.junit.extensions.listeners;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestListener;
-
-import java.util.Properties;
-
-/**
- * TKTestListener is a listener interface for listeners that want to be informed of the run times of tests, the memory
- * usage of tests, the 'size' parameters of parameterized tests and the begin and end events of complete test runs.
- * {@link org.apache.qpid.junit.extensions.TKTestResult} is an example of a test result class that listeners
- * interested in these events can be attached to.
- *
- * The {@link #timing(junit.framework.Test, long, Long)}, {@link #memoryUsed(junit.framework.Test, long, long, Long)},
- * {@link #parameterValue(junit.framework.Test, int, Long)} and {@link #endTest(junit.framework.Test, Long)} methods
- * all accept on optional thread id parameter.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Listen to test timings.
- * <tr><td> Listen to test memory usages.
- * <tr><td> Listen to parameterized test parameters.
- * </table>
- *
- * @author Rupert Smith
- */
-public interface TKTestListener extends TestListener
-{
- /**
- * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
- *
- * @param test The test to resest any results for.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void reset(Test test, Long threadId);
-
- /**
- * Should be called every time a test completes with the run time of that test.
- *
- * @param test The name of the test.
- * @param nanos The run time of the test in nanoseconds.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void timing(Test test, long nanos, Long threadId);
-
- /**
- * Should be called every time a test completed with the amount of memory used before and after the test was run.
- *
- * @param test The test which memory was measured for.
- * @param memStart The total JVM memory used before the test was run.
- * @param memEnd The total JVM memory used after the test was run.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void memoryUsed(Test test, long memStart, long memEnd, Long threadId);
-
- /**
- * Should be called every time a parameterized test completed with the int value of its test parameter.
- *
- * @param test The test which memory was measured for.
- * @param parameter The int parameter value.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void parameterValue(Test test, int parameter, Long threadId);
-
- /**
- * Should be called every time a test completes with the current number of test threads running.
- *
- * @param test The test for which the measurement is being generated.
- * @param threads The number of tests being run concurrently.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void concurrencyLevel(Test test, int threads, Long threadId);
-
- /**
- * Called when a test completes. Success, failure and errors. This method should be used when registering an
- * end test from a different thread than the one that started the test.
- *
- * @param test The test which completed.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void endTest(Test test, Long threadId);
-
- /**
- * Called when a test completes to mark it as a test fail. This method should be used when registering a
- * failure from a different thread than the one that started the test.
- *
- * @param test The test which failed.
- * @param e The assertion that failed the test.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void addFailure(Test test, AssertionFailedError e, Long threadId);
-
- /**
- * Notifies listeners of the start of a complete run of tests.
- */
- public void startBatch();
-
- /**
- * Notifies listeners of the end of a complete run of tests.
- *
- * @param parameters The optional test parameters to log out with the batch results.
- */
- public void endBatch(Properties parameters);
-
- /**
- * Notifies listeners of the tests read/set properties.
- *
- * @param properties The tests read/set properties.
- */
- public void properties(Properties properties);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.listeners;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+
+import java.util.Properties;
+
+/**
+ * TKTestListener is a listener interface for listeners that want to be informed of the run times of tests, the memory
+ * usage of tests, the 'size' parameters of parameterized tests and the begin and end events of complete test runs.
+ * {@link org.apache.qpid.junit.extensions.TKTestResult} is an example of a test result class that listeners
+ * interested in these events can be attached to.
+ *
+ * The {@link #timing(junit.framework.Test, long, Long)}, {@link #memoryUsed(junit.framework.Test, long, long, Long)},
+ * {@link #parameterValue(junit.framework.Test, int, Long)} and {@link #endTest(junit.framework.Test, Long)} methods
+ * all accept on optional thread id parameter.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Listen to test timings.
+ * <tr><td> Listen to test memory usages.
+ * <tr><td> Listen to parameterized test parameters.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public interface TKTestListener extends TestListener
+{
+ /**
+ * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
+ *
+ * @param test The test to resest any results for.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void reset(Test test, Long threadId);
+
+ /**
+ * Should be called every time a test completes with the run time of that test.
+ *
+ * @param test The name of the test.
+ * @param nanos The run time of the test in nanoseconds.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void timing(Test test, long nanos, Long threadId);
+
+ /**
+ * Should be called every time a test completed with the amount of memory used before and after the test was run.
+ *
+ * @param test The test which memory was measured for.
+ * @param memStart The total JVM memory used before the test was run.
+ * @param memEnd The total JVM memory used after the test was run.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void memoryUsed(Test test, long memStart, long memEnd, Long threadId);
+
+ /**
+ * Should be called every time a parameterized test completed with the int value of its test parameter.
+ *
+ * @param test The test which memory was measured for.
+ * @param parameter The int parameter value.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void parameterValue(Test test, int parameter, Long threadId);
+
+ /**
+ * Should be called every time a test completes with the current number of test threads running.
+ *
+ * @param test The test for which the measurement is being generated.
+ * @param threads The number of tests being run concurrently.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void concurrencyLevel(Test test, int threads, Long threadId);
+
+ /**
+ * Called when a test completes. Success, failure and errors. This method should be used when registering an
+ * end test from a different thread than the one that started the test.
+ *
+ * @param test The test which completed.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void endTest(Test test, Long threadId);
+
+ /**
+ * Called when a test completes to mark it as a test fail. This method should be used when registering a
+ * failure from a different thread than the one that started the test.
+ *
+ * @param test The test which failed.
+ * @param e The assertion that failed the test.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void addFailure(Test test, AssertionFailedError e, Long threadId);
+
+ /**
+ * Notifies listeners of the start of a complete run of tests.
+ */
+ public void startBatch();
+
+ /**
+ * Notifies listeners of the end of a complete run of tests.
+ *
+ * @param parameters The optional test parameters to log out with the batch results.
+ */
+ public void endBatch(Properties parameters);
+
+ /**
+ * Notifies listeners of the tests read/set properties.
+ *
+ * @param properties The tests read/set properties.
+ */
+ public void properties(Properties properties);
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java
index a88837e323..ded07ef5bb 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/listeners/XMLTestListener.java
@@ -1,400 +1,400 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.listeners;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestCase;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.ShutdownHookable;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.*;
-
-/**
- * Listens for test results for a named test and outputs these in the standard JUnit XML format to the specified
- * writer.
- *
- * <p/>The API for this listener accepts notifications about different aspects of a tests results through different
- * methods, so some assumption needs to be made as to which test result a notification refers to. For example
- * {@link #startTest} will be called, then possibly {@link #timing} will be called, even though the test instance is
- * passed in both cases, it is not enough to distinguish a particular run of the test, as the test case instance may
- * be being shared between multiple threads, or being run a repeated number of times, and can therfore be re-used
- * between calls. The listeners make the assumption that, for every test, a unique thread will call {@link #startTest}
- * and {@link #endTest} to delimit each test. All calls to set test parameters, timings, state and so on, will occur
- * between the start and end and will be given with the same thread id as the start and end, so the thread id provides
- * a unqiue value to identify a particular test run against.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Listen to test lifecycle notifications.
- * <tr><td> Listen to test errors and failures.
- * <tr><td> Listen to test timings.
- * <tr><td> Listen to test memory usages.
- * <tr><td> Listen to parameterized test parameters.
- * <tr><th> Responsibilities
- * </table>
- *
- * @todo Merge this class with CSV test listener, making the collection of results common to both, and only factoring
- * out the results printing code into sub-classes. Provide a simple XML results formatter with the same format as
- * the ant XML formatter, and a more structured one for outputing results with timings and summaries from
- * performance tests.
- *
- * @author Rupert Smith
- */
-public class XMLTestListener implements TKTestListener, ShutdownHookable
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(XMLTestListener.class);
-
- /** The results file writer. */
- protected Writer writer;
-
- /** Holds the results for individual tests. */
- // protected Map<Result, Result> results = new LinkedHashMap<Result, Result>();
- // protected List<Result> results = new ArrayList<Result>();
-
- /**
- * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an
- * explicit thread id must be used, where notifications come from different threads than the ones that called
- * the test method.
- */
- Map<Long, Result> threadLocalResults = Collections.synchronizedMap(new LinkedHashMap<Long, Result>());
-
- /**
- * Holds results for tests that have ended. Transferring these results here from the per-thread results map, means
- * that the thread id is freed for the thread to generate more results.
- */
- List<Result> results = new ArrayList<Result>();
-
- /** Holds the overall error count. */
- protected int errors = 0;
-
- /** Holds the overall failure count. */
- protected int failures = 0;
-
- /** Holds the overall tests run count. */
- protected int runs = 0;
-
- /** Holds the name of the class that tests are being run for. */
- String testClassName;
-
- /**
- * Creates a new XML results output listener that writes to the specified location.
- *
- * @param writer The location to write results to.
- * @param testClassName The name of the test class to include in the test results.
- */
- public XMLTestListener(Writer writer, String testClassName)
- {
- log.debug("public XMLTestListener(Writer writer, String testClassName = " + testClassName + "): called");
-
- this.writer = writer;
- this.testClassName = testClassName;
- }
-
- /**
- * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
- *
- * @param test The test to resest any results for.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void reset(Test test, Long threadId)
- {
- log.debug("public void reset(Test test = " + test + ", Long threadId = " + threadId + "): called");
-
- XMLTestListener.Result r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
-
- r.error = null;
- r.failure = null;
-
- }
-
- /**
- * Notification that a test started.
- *
- * @param test The test that started.
- */
- public void startTest(Test test)
- {
- log.debug("public void startTest(Test test = " + test + "): called");
-
- Result newResult = new Result(test.getClass().getName(), ((TestCase) test).getName());
-
- // Initialize the thread local test results.
- threadLocalResults.put(Thread.currentThread().getId(), newResult);
- runs++;
- }
-
- /**
- * Should be called every time a test completes with the run time of that test.
- *
- * @param test The name of the test.
- * @param nanos The run time of the test in nanoseconds.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void timing(Test test, long nanos, Long threadId)
- { }
-
- /**
- * Should be called every time a test completed with the amount of memory used before and after the test was run.
- *
- * @param test The test which memory was measured for.
- * @param memStart The total JVM memory used before the test was run.
- * @param memEnd The total JVM memory used after the test was run.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
- { }
-
- /**
- * Should be called every time a parameterized test completed with the int value of its test parameter.
- *
- * @param test The test which memory was measured for.
- * @param parameter The int parameter value.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void parameterValue(Test test, int parameter, Long threadId)
- { }
-
- /**
- * Should be called every time a test completes with the current number of test threads running.
- *
- * @param test The test for which the measurement is being generated.
- * @param threads The number of tests being run concurrently.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void concurrencyLevel(Test test, int threads, Long threadId)
- { }
-
- /**
- * Notifies listeners of the tests read/set properties.
- *
- * @param properties The tests read/set properties.
- */
- public void properties(Properties properties)
- { }
-
- /**
- * Notification that a test ended.
- *
- * @param test The test that ended.
- */
- public void endTest(Test test)
- {
- log.debug("public void endTest(Test test = " + test + "): called");
-
- // Move complete test results into the completed tests list.
- Result r = threadLocalResults.get(Thread.currentThread().getId());
- results.add(r);
-
- // Clear all the test results for the thread.
- threadLocalResults.remove(Thread.currentThread().getId());
- }
-
- /**
- * Called when a test completes. Success, failure and errors. This method should be used when registering an
- * end test from a different thread than the one that started the test.
- *
- * @param test The test which completed.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void endTest(Test test, Long threadId)
- {
- log.debug("public void endTest(Test test = " + test + ", Long threadId = " + threadId + "): called");
-
- // Move complete test results into the completed tests list.
- Result r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
- results.add(r);
-
- // Clear all the test results for the thread.
- threadLocalResults.remove(Thread.currentThread().getId());
- }
-
- /**
- * An error occurred.
- *
- * @param test The test in which the error occurred.
- * @param t The throwable that resulted from the error.
- */
- public void addError(Test test, Throwable t)
- {
- log.debug("public void addError(Test test = " + test + ", Throwable t = " + t + "): called");
-
- Result r = threadLocalResults.get(Thread.currentThread().getId());
- r.error = t;
- errors++;
- }
-
- /**
- * A failure occurred.
- *
- * @param test The test in which the failure occurred.
- * @param t The JUnit assertions that led to the failure.
- */
- public void addFailure(Test test, AssertionFailedError t)
- {
- log.debug("public void addFailure(Test test = " + test + ", AssertionFailedError t = " + t + "): called");
-
- Result r = threadLocalResults.get(Thread.currentThread().getId());
- r.failure = t;
- failures++;
- }
-
- /**
- * Called when a test completes to mark it as a test fail. This method should be used when registering a
- * failure from a different thread than the one that started the test.
- *
- * @param test The test which failed.
- * @param e The assertion that failed the test.
- * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
- */
- public void addFailure(Test test, AssertionFailedError e, Long threadId)
- {
- log.debug("public void addFailure(Test test, AssertionFailedError e, Long threadId): called");
-
- Result r =
- (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
- r.failure = e;
- failures++;
- }
-
- /**
- * Notifies listeners of the start of a complete run of tests.
- */
- public void startBatch()
- {
- log.debug("public void startBatch(): called");
-
- // Reset all results counts.
- threadLocalResults = Collections.synchronizedMap(new HashMap<Long, Result>());
- errors = 0;
- failures = 0;
- runs = 0;
-
- // Write out the file header.
- try
- {
- writer.write("<?xml version=\"1.0\" ?>\n");
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write the test results.", e);
- }
- }
-
- /**
- * Notifies listeners of the end of a complete run of tests.
- *
- * @param parameters The optional test parameters to log out with the batch results.
- */
- public void endBatch(Properties parameters)
- {
- log.debug("public void endBatch(Properties parameters = " + parameters + "): called");
-
- // Write out the results.
- try
- {
- // writer.write("<?xml version=\"1.0\" ?>\n");
- writer.write("<testsuite errors=\"" + errors + "\" failures=\"" + failures + "\" tests=\"" + runs + "\" name=\""
- + testClassName + "\">\n");
-
- for (Result result : results)
- {
- writer.write(" <testcase classname=\"" + result.testClass + "\" name=\"" + result.testName + "\">\n");
-
- if (result.error != null)
- {
- writer.write(" <error type=\"" + result.error.getClass() + "\">");
- result.error.printStackTrace(new PrintWriter(writer));
- writer.write(" </error>");
- }
- else if (result.failure != null)
- {
- writer.write(" <failure type=\"" + result.failure.getClass() + "\">");
- result.failure.printStackTrace(new PrintWriter(writer));
- writer.write(" </failure>");
- }
-
- writer.write(" </testcase>\n");
- }
-
- writer.write("</testsuite>\n");
- writer.flush();
- }
- catch (IOException e)
- {
- throw new RuntimeException("Unable to write the test results.", e);
- }
- }
-
- /**
- * Supplies the shutdown hook.
- *
- * @return The shut down hook.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- log.debug("XMLTestListener::ShutdownHook: called");
- }
- });
- }
-
- /**
- * Used to capture the results of a particular test run.
- */
- protected static class Result
- {
- /** Holds the name of the test class. */
- public String testClass;
-
- /** Holds the name of the test method. */
- public String testName;
-
- /** Holds the exception that caused error in this test. */
- public Throwable error;
-
- /** Holds the assertion exception that caused failure in this test. */
- public AssertionFailedError failure;
-
- /**
- * Creates a placeholder for the results of a test.
- *
- * @param testClass The test class.
- * @param testName The name of the test that was run.
- */
- public Result(String testClass, String testName)
- {
- this.testClass = testClass;
- this.testName = testName;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.listeners;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.ShutdownHookable;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.*;
+
+/**
+ * Listens for test results for a named test and outputs these in the standard JUnit XML format to the specified
+ * writer.
+ *
+ * <p/>The API for this listener accepts notifications about different aspects of a tests results through different
+ * methods, so some assumption needs to be made as to which test result a notification refers to. For example
+ * {@link #startTest} will be called, then possibly {@link #timing} will be called, even though the test instance is
+ * passed in both cases, it is not enough to distinguish a particular run of the test, as the test case instance may
+ * be being shared between multiple threads, or being run a repeated number of times, and can therfore be re-used
+ * between calls. The listeners make the assumption that, for every test, a unique thread will call {@link #startTest}
+ * and {@link #endTest} to delimit each test. All calls to set test parameters, timings, state and so on, will occur
+ * between the start and end and will be given with the same thread id as the start and end, so the thread id provides
+ * a unqiue value to identify a particular test run against.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Listen to test lifecycle notifications.
+ * <tr><td> Listen to test errors and failures.
+ * <tr><td> Listen to test timings.
+ * <tr><td> Listen to test memory usages.
+ * <tr><td> Listen to parameterized test parameters.
+ * <tr><th> Responsibilities
+ * </table>
+ *
+ * @todo Merge this class with CSV test listener, making the collection of results common to both, and only factoring
+ * out the results printing code into sub-classes. Provide a simple XML results formatter with the same format as
+ * the ant XML formatter, and a more structured one for outputing results with timings and summaries from
+ * performance tests.
+ *
+ * @author Rupert Smith
+ */
+public class XMLTestListener implements TKTestListener, ShutdownHookable
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(XMLTestListener.class);
+
+ /** The results file writer. */
+ protected Writer writer;
+
+ /** Holds the results for individual tests. */
+ // protected Map<Result, Result> results = new LinkedHashMap<Result, Result>();
+ // protected List<Result> results = new ArrayList<Result>();
+
+ /**
+ * Map for holding results on a per thread basis as they come in. A ThreadLocal is not used as sometimes an
+ * explicit thread id must be used, where notifications come from different threads than the ones that called
+ * the test method.
+ */
+ Map<Long, Result> threadLocalResults = Collections.synchronizedMap(new LinkedHashMap<Long, Result>());
+
+ /**
+ * Holds results for tests that have ended. Transferring these results here from the per-thread results map, means
+ * that the thread id is freed for the thread to generate more results.
+ */
+ List<Result> results = new ArrayList<Result>();
+
+ /** Holds the overall error count. */
+ protected int errors = 0;
+
+ /** Holds the overall failure count. */
+ protected int failures = 0;
+
+ /** Holds the overall tests run count. */
+ protected int runs = 0;
+
+ /** Holds the name of the class that tests are being run for. */
+ String testClassName;
+
+ /**
+ * Creates a new XML results output listener that writes to the specified location.
+ *
+ * @param writer The location to write results to.
+ * @param testClassName The name of the test class to include in the test results.
+ */
+ public XMLTestListener(Writer writer, String testClassName)
+ {
+ log.debug("public XMLTestListener(Writer writer, String testClassName = " + testClassName + "): called");
+
+ this.writer = writer;
+ this.testClassName = testClassName;
+ }
+
+ /**
+ * Resets the test results to the default state of time zero, memory usage zero, parameter zero, test passed.
+ *
+ * @param test The test to resest any results for.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void reset(Test test, Long threadId)
+ {
+ log.debug("public void reset(Test test = " + test + ", Long threadId = " + threadId + "): called");
+
+ XMLTestListener.Result r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+
+ r.error = null;
+ r.failure = null;
+
+ }
+
+ /**
+ * Notification that a test started.
+ *
+ * @param test The test that started.
+ */
+ public void startTest(Test test)
+ {
+ log.debug("public void startTest(Test test = " + test + "): called");
+
+ Result newResult = new Result(test.getClass().getName(), ((TestCase) test).getName());
+
+ // Initialize the thread local test results.
+ threadLocalResults.put(Thread.currentThread().getId(), newResult);
+ runs++;
+ }
+
+ /**
+ * Should be called every time a test completes with the run time of that test.
+ *
+ * @param test The name of the test.
+ * @param nanos The run time of the test in nanoseconds.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void timing(Test test, long nanos, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a test completed with the amount of memory used before and after the test was run.
+ *
+ * @param test The test which memory was measured for.
+ * @param memStart The total JVM memory used before the test was run.
+ * @param memEnd The total JVM memory used after the test was run.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void memoryUsed(Test test, long memStart, long memEnd, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a parameterized test completed with the int value of its test parameter.
+ *
+ * @param test The test which memory was measured for.
+ * @param parameter The int parameter value.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void parameterValue(Test test, int parameter, Long threadId)
+ { }
+
+ /**
+ * Should be called every time a test completes with the current number of test threads running.
+ *
+ * @param test The test for which the measurement is being generated.
+ * @param threads The number of tests being run concurrently.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void concurrencyLevel(Test test, int threads, Long threadId)
+ { }
+
+ /**
+ * Notifies listeners of the tests read/set properties.
+ *
+ * @param properties The tests read/set properties.
+ */
+ public void properties(Properties properties)
+ { }
+
+ /**
+ * Notification that a test ended.
+ *
+ * @param test The test that ended.
+ */
+ public void endTest(Test test)
+ {
+ log.debug("public void endTest(Test test = " + test + "): called");
+
+ // Move complete test results into the completed tests list.
+ Result r = threadLocalResults.get(Thread.currentThread().getId());
+ results.add(r);
+
+ // Clear all the test results for the thread.
+ threadLocalResults.remove(Thread.currentThread().getId());
+ }
+
+ /**
+ * Called when a test completes. Success, failure and errors. This method should be used when registering an
+ * end test from a different thread than the one that started the test.
+ *
+ * @param test The test which completed.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void endTest(Test test, Long threadId)
+ {
+ log.debug("public void endTest(Test test = " + test + ", Long threadId = " + threadId + "): called");
+
+ // Move complete test results into the completed tests list.
+ Result r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+ results.add(r);
+
+ // Clear all the test results for the thread.
+ threadLocalResults.remove(Thread.currentThread().getId());
+ }
+
+ /**
+ * An error occurred.
+ *
+ * @param test The test in which the error occurred.
+ * @param t The throwable that resulted from the error.
+ */
+ public void addError(Test test, Throwable t)
+ {
+ log.debug("public void addError(Test test = " + test + ", Throwable t = " + t + "): called");
+
+ Result r = threadLocalResults.get(Thread.currentThread().getId());
+ r.error = t;
+ errors++;
+ }
+
+ /**
+ * A failure occurred.
+ *
+ * @param test The test in which the failure occurred.
+ * @param t The JUnit assertions that led to the failure.
+ */
+ public void addFailure(Test test, AssertionFailedError t)
+ {
+ log.debug("public void addFailure(Test test = " + test + ", AssertionFailedError t = " + t + "): called");
+
+ Result r = threadLocalResults.get(Thread.currentThread().getId());
+ r.failure = t;
+ failures++;
+ }
+
+ /**
+ * Called when a test completes to mark it as a test fail. This method should be used when registering a
+ * failure from a different thread than the one that started the test.
+ *
+ * @param test The test which failed.
+ * @param e The assertion that failed the test.
+ * @param threadId Optional thread id if not calling from thread that started the test method. May be null.
+ */
+ public void addFailure(Test test, AssertionFailedError e, Long threadId)
+ {
+ log.debug("public void addFailure(Test test, AssertionFailedError e, Long threadId): called");
+
+ Result r =
+ (threadId == null) ? threadLocalResults.get(Thread.currentThread().getId()) : threadLocalResults.get(threadId);
+ r.failure = e;
+ failures++;
+ }
+
+ /**
+ * Notifies listeners of the start of a complete run of tests.
+ */
+ public void startBatch()
+ {
+ log.debug("public void startBatch(): called");
+
+ // Reset all results counts.
+ threadLocalResults = Collections.synchronizedMap(new HashMap<Long, Result>());
+ errors = 0;
+ failures = 0;
+ runs = 0;
+
+ // Write out the file header.
+ try
+ {
+ writer.write("<?xml version=\"1.0\" ?>\n");
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write the test results.", e);
+ }
+ }
+
+ /**
+ * Notifies listeners of the end of a complete run of tests.
+ *
+ * @param parameters The optional test parameters to log out with the batch results.
+ */
+ public void endBatch(Properties parameters)
+ {
+ log.debug("public void endBatch(Properties parameters = " + parameters + "): called");
+
+ // Write out the results.
+ try
+ {
+ // writer.write("<?xml version=\"1.0\" ?>\n");
+ writer.write("<testsuite errors=\"" + errors + "\" failures=\"" + failures + "\" tests=\"" + runs + "\" name=\""
+ + testClassName + "\">\n");
+
+ for (Result result : results)
+ {
+ writer.write(" <testcase classname=\"" + result.testClass + "\" name=\"" + result.testName + "\">\n");
+
+ if (result.error != null)
+ {
+ writer.write(" <error type=\"" + result.error.getClass() + "\">");
+ result.error.printStackTrace(new PrintWriter(writer));
+ writer.write(" </error>");
+ }
+ else if (result.failure != null)
+ {
+ writer.write(" <failure type=\"" + result.failure.getClass() + "\">");
+ result.failure.printStackTrace(new PrintWriter(writer));
+ writer.write(" </failure>");
+ }
+
+ writer.write(" </testcase>\n");
+ }
+
+ writer.write("</testsuite>\n");
+ writer.flush();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Unable to write the test results.", e);
+ }
+ }
+
+ /**
+ * Supplies the shutdown hook.
+ *
+ * @return The shut down hook.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ log.debug("XMLTestListener::ShutdownHook: called");
+ }
+ });
+ }
+
+ /**
+ * Used to capture the results of a particular test run.
+ */
+ protected static class Result
+ {
+ /** Holds the name of the test class. */
+ public String testClass;
+
+ /** Holds the name of the test method. */
+ public String testName;
+
+ /** Holds the exception that caused error in this test. */
+ public Throwable error;
+
+ /** Holds the assertion exception that caused failure in this test. */
+ public AssertionFailedError failure;
+
+ /**
+ * Creates a placeholder for the results of a test.
+ *
+ * @param testClass The test class.
+ * @param testName The name of the test that was run.
+ */
+ public Result(String testClass, String testName)
+ {
+ this.testClass = testClass;
+ this.testName = testName;
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java
index 61c58bf3ba..f158090e96 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/CommandLineParser.java
@@ -1,787 +1,787 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * CommandLineParser provides a utility for specifying the format of a command line and parsing command lines to ensure
- * that they fit their specified format. A command line is made up of flags and options, both may be refered to as
- * options. A flag is an option that does not take an argument (specifying it means it has the value 'true' and not
- * specifying it means it has the value 'false'). Options must take arguments but they can be set up with defaults so
- * that they take a default value when not set. Options may be mandatory in wich case it is an error not to specify
- * them on the command line. Flags are never mandatory because they are implicitly set to false when not specified.
- *
- * <p/>Some examples command line are:
- *
- * <ul>
- * <li>This one has two options that expect arguments:
- * <pre>
- * cruisecontrol -configfile cruisecontrol.xml -port 9000
- * </pre>
- * <li>This has one no-arg flag and two 'free' arguments:
- * <pre>
- * zip -r project.zip project/*
- * </pre>
- * <li>This one concatenates multiple flags into a single block with only one '-':
- * <pre>
- * jar -tvf mytar.tar
- * </pre>
- *
- * <p/>The parsing rules are:
- *
- * <ol>
- * <li>Flags may be combined after a single '-' because they never take arguments. Normally such flags are single letter
- * flags but this is only a convention and not enforced. Flags of more than one letter are usually specified on their own.
- * <li>Options expecting arguments must always be on their own.
- * <li>The argument to an option may be seperated from it by whitespace or appended directly onto the option.
- * <li>The argument to an option may never begin with a '-' character.
- * <li>All other arguments not beginning with a '-' character are free arguments that do not belong to any option.
- * <li>The second or later of a set of duplicate or repeated flags override earlier ones.
- * <li>Options are matched up to the shortest matching option. This is because of the possibility of having no space
- * between an option and its argument. This rules out the possibility of using two options where one is an opening
- * substring of the other. For example, the options "foo" and "foobar" cannot be used on the same command line because
- * it is not possible to distinguish the argument "-foobar" from being the "foobar" option or the "foo" option with
- * the "bar" argument.
- * </ol>
- *
- * <p/>By default, unknown options are simply ignored if specified on the command line. This behaviour may be changed
- * so that the parser reports all unknowns as errors by using the {@link #setErrorsOnUnknowns} method.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Accept a command line specification.
- * <tr><td> Parse a command line into properties, validating it against its specification.
- * <tr><td> Report all errors between a command line and its specification.
- * <tr><td> Provide a formatted usage string for a command line.
- * <tr><td> Provide a formatted options in force string for a command line.
- * <tr><td> Allow errors on unknowns behaviour to be turned on or off.
- * </table>
- *
- * @author Rupert Smith
- */
-public class CommandLineParser
-{
- /**
- * Holds a mapping from command line option names to detailed information about those options.
- * Use of a tree map ensures that the options are easy to print in alphabetical order as a usage string.
- * An alternative might be to use a LinkedHashMap to print them in the order they are specified.
- */
- private Map<String, CommandLineOption> optionMap = new TreeMap<String, CommandLineOption>();
-
- /** Holds a list of parsing errors. */
- private List<String> parsingErrors = new ArrayList<String>();
-
- /** Holds the regular head matcher to match command line options with. */
- private Matcher optionMatcher = null;
-
- /** Holds the parsed command line properties after parsing. */
- private Properties parsedProperties = null;
-
- /** Holds any trailing name=value pairs specified in the free arguments. */
- private Properties trailingProperties = null;
-
- /** Flag used to indicate that errors should be created for unknown options. False by default. */
- private boolean errorsOnUnknowns = false;
-
- /**
- * Creates a command line options parser from a command line specification. This is passed to this constructor
- * as an array of arrays of strings. Each array of strings specifies the command line for a single option. A static
- * array may therefore easily be used to configure the command line parser in a single method call with an easily
- * readable format.
- *
- * <p/>Each array of strings must be 2, 3, 4 or 5 elements long. If any of the last three elements are missing they
- * are assumed to be null. The elements specify the following parameters:
- * <ol>
- * <li>The name of the option without the leading '-'. For example, "file". To specify the format of the 'free'
- * arguments use the option names "1", "2", ... and so on.
- * <li>The option comment. A line of text describing the usage of the option. For example, "The file to be processed."
- * <li>The options argument. This is a very short description of the argument to the option, often a single word
- * or a reminder as to the arguments format. When this element is null the option is a flag and does not
- * accept any arguments. For example, "filename" or "(unix | windows)" or null. The actual text specified
- * is only used to print in the usage message to remind the user of the usage of the option.
- * <li>The mandatory flag. When set to "true" an option must always be specified. Any other value, including null,
- * means that the option is mandatory. Flags are always mandatory (see class javadoc for explanation of why) so
- * this is ignored for flags.
- * <li>A regular head describing the format that the argument must take. Ignored if null.
- * </ol>
- * <p/>An example call to this constructor is:
- *
- * <pre>
- * CommandLineParser commandLine = new CommandLineParser(
- * new String[][] {{"file", "The file to be processed. ", "filename", "true"},
- * {"dir", "Directory to store results in. Current dir used if not set.", "out dir"},
- * {"os", "Operating system EOL format to use.", "(windows | unix)", null, "windows\|unix"},
- * {"v", "Verbose mode. Prints information about the processing as it goes."},
- * {"1", "The processing command to run.", "command", "true", "add\|remove\|list"}});
- * </pre>
- *
- * @param config The configuration as an array of arrays of strings.
- */
- public CommandLineParser(String[][] config)
- {
- // Loop through all the command line option specifications creating details for each in the options map.
- for (String[] nextOptionSpec : config)
- {
- addOption(nextOptionSpec[0], nextOptionSpec[1], (nextOptionSpec.length > 2) ? nextOptionSpec[2] : null,
- (nextOptionSpec.length > 3) && ("true".equals(nextOptionSpec[3])),
- (nextOptionSpec.length > 4) ? nextOptionSpec[4] : null);
- }
- }
-
- /**
- * Extracts all name=value pairs from the command line, sets them all as system properties and also returns
- * a map of properties containing them.
- *
- * @param args The command line.
- * @param commandLine The command line parser.
- * @param properties The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
- *
- * @return A set of properties containing all name=value pairs from the command line.
- */
- public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
- {
- // Capture the command line arguments or display errors and correct usage and then exit.
- Properties options = null;
-
- try
- {
- options = commandLine.parseCommandLine(args);
-
- // Add all the command line options and trailing settings to properties if the optional properties object
- // to copy them into has been set.
- if (properties != null)
- {
- commandLine.addTrailingPairsToProperties(properties);
- commandLine.addOptionsToProperties(properties);
- }
- }
- catch (IllegalArgumentException e)
- {
- System.out.println(commandLine.getErrors());
- System.out.println(commandLine.getUsage());
- System.exit(1);
- }
-
- return options;
- }
-
- /**
- * Lists all the parsing errors from the most recent parsing in a string.
- *
- * @return All the parsing errors from the most recent parsing.
- */
- public String getErrors()
- {
- // Return the empty string if there are no errors.
- if (parsingErrors.isEmpty())
- {
- return "";
- }
-
- // Concatenate all the parsing errors together.
- String result = "";
-
- for (String s : parsingErrors)
- {
- result += s;
- }
-
- return result;
- }
-
- /**
- * Lists the properties set from the most recent parsing or an empty string if no parsing has been done yet.
- *
- * @return The properties set from the most recent parsing or an empty string if no parsing has been done yet.
- */
- public String getOptionsInForce()
- {
- // Check if there are no properties to report and return and empty string if so.
- if (parsedProperties == null)
- {
- return "";
- }
-
- // List all the properties.
- String result = "Options in force:\n";
-
- for (Map.Entry<Object, Object> property : parsedProperties.entrySet())
- {
- result += property.getKey() + " = " + property.getValue() + "\n";
- }
-
- return result;
- }
-
- /**
- * Generates a usage string consisting of the name of each option and each options argument description and
- * comment.
- *
- * @return A usage string for all the options.
- */
- public String getUsage()
- {
- String result = "Options:\n";
-
- int optionWidth = 0;
- int argumentWidth = 0;
-
- // Calculate the column widths required for aligned layout.
- for (CommandLineOption optionInfo : optionMap.values())
- {
- int oWidth = optionInfo.option.length();
- int aWidth = (optionInfo.argument != null) ? (optionInfo.argument.length()) : 0;
-
- optionWidth = (oWidth > optionWidth) ? oWidth : optionWidth;
- argumentWidth = (aWidth > argumentWidth) ? aWidth : argumentWidth;
- }
-
- // Print usage on each of the command line options.
- for (CommandLineOption optionInfo : optionMap.values())
- {
- String argString = ((optionInfo.argument != null) ? (optionInfo.argument) : "");
- String optionString = optionInfo.option;
-
- argString = rightPad(argString, " ", argumentWidth);
- optionString = rightPad(optionString, " ", optionWidth);
-
- result += "-" + optionString + " " + argString + " " + optionInfo.comment + "\n";
- }
-
- return result;
- }
-
- /**
- * Right pads a string with a given string to a given size. This method will repeat the padder string as many
- * times as is necessary until the exact specified size is reached. If the specified size is less than the size
- * of the original string then the original string is returned unchanged.
- *
- * <pre>
- * Example1 - original string "cat", padder string "white", size 8 gives "catwhite".
- * Example2 - original string "cat", padder string "white", size 15 gives "catwhitewhitewh".
- * Example3 - original string "cat", padder string "white", size 2 gives "cat".
- * </pre>
- *
- * @param stringToPad The original string.
- * @param padder The string to pad onto the original string.
- * @param size The required size of the new string.
- *
- * @return The newly padded string.
- */
- public static String rightPad(String stringToPad, String padder, int size)
- {
- if (padder.length() == 0)
- {
- return stringToPad;
- }
-
- StringBuffer strb = new StringBuffer(stringToPad);
- StringCharacterIterator sci = new StringCharacterIterator(padder);
-
- while (strb.length() < size)
- {
- for (char ch = sci.first(); ch != CharacterIterator.DONE; ch = sci.next())
- {
- if (strb.length() < size)
- {
- strb.append(String.valueOf(ch));
- }
- }
- }
-
- return strb.toString();
- }
-
- /**
- * Control the behaviour of the errors on unkowns reporting. When turned on this reports all unkowns options
- * as errors. When turned off, all unknowns are simply ignored.
- *
- * @param errors The setting of the errors on unkown flag. True to turn it on.
- */
- public void setErrorsOnUnknowns(boolean errors)
- {
- errorsOnUnknowns = errors;
- }
-
- /**
- * Parses a set of command line arguments into a set of properties, keyed by the argument flag. The free arguments
- * are keyed by integers as strings starting at "1" and then "2", ... and so on.
- *
- * <p/>See the class level comment for a description of the parsing rules.
- *
- * @param args The command line arguments.
- *
- * @return The arguments as a set of properties.
- *
- * @throws IllegalArgumentException If the command line cannot be parsed against its specification. If this exception
- * is thrown a call to {@link #getErrors} will provide a diagnostic of the command
- * line errors.
- */
- public Properties parseCommandLine(String[] args) throws IllegalArgumentException
- {
- Properties options = new Properties();
-
- // Used to keep count of the current 'free' argument.
- int free = 1;
-
- // Used to indicate that the most recently parsed option is expecting arguments.
- boolean expectingArgs = false;
-
- // The option that is expecting arguments from the next element of the command line.
- String optionExpectingArgs = null;
-
- // Used to indicate that the most recently parsed option is a duplicate and should be ignored.
- // boolean ignore = false;
-
- // Create the regular head matcher for the command line options.
- String regexp = "^(";
- int optionsAdded = 0;
-
- for (Iterator<String> i = optionMap.keySet().iterator(); i.hasNext();)
- {
- String nextOption = i.next();
-
- // Check that the option is not a free argument definition.
- boolean notFree = false;
-
- try
- {
- Integer.parseInt(nextOption);
- }
- catch (NumberFormatException e)
- {
- notFree = true;
- }
-
- // Add the option to the regular head matcher if it is not a free argument definition.
- if (notFree)
- {
- regexp += nextOption + (i.hasNext() ? "|" : "");
- optionsAdded++;
- }
- }
-
- // There has to be more that one option in the regular head or else the compiler complains that the close
- // cannot be nullable if the '?' token is used to make the matched option string optional.
- regexp += ")" + ((optionsAdded > 0) ? "?" : "") + "(.*)";
- Pattern pattern = Pattern.compile(regexp);
-
- // Loop through all the command line arguments.
- for (String arg1 : args)
- {
- // Check if the next command line argument begins with a '-' character and is therefore the start of
- // an option.
- if (arg1.startsWith("-"))
- {
- // Extract the value of the option without the leading '-'.
- String arg = arg1.substring(1);
-
- // Match up to the longest matching option.
- optionMatcher = pattern.matcher(arg);
- optionMatcher.matches();
-
- String matchedOption = optionMatcher.group(1);
-
- // Match any argument directly appended onto the longest matching option.
- String matchedArg = optionMatcher.group(2);
-
- // Check that a known option was matched.
- if ((matchedOption != null) && !"".equals(matchedOption))
- {
- // Get the command line option information for the matched option.
- CommandLineOption optionInfo = optionMap.get(matchedOption);
-
- // Check if this option is expecting arguments.
- if (optionInfo.expectsArgs)
- {
- // The option is expecting arguments so swallow the next command line argument as an
- // argument to this option.
- expectingArgs = true;
- optionExpectingArgs = matchedOption;
-
- // In the mean time set this options argument to the empty string in case no argument is ever
- // supplied.
- // options.put(matchedOption, "");
- }
-
- // Check if the option was matched on its own and is a flag in which case set that flag.
- if ("".equals(matchedArg) && !optionInfo.expectsArgs)
- {
- options.put(matchedOption, "true");
- }
- // The option was matched as a substring with its argument appended to it or is a flag that is
- // condensed together with other flags.
- else if (!"".equals(matchedArg))
- {
- // Check if the option is a flag and therefore is allowed to be condensed together
- // with other flags.
- if (!optionInfo.expectsArgs)
- {
- // Set the first matched flag.
- options.put(matchedOption, "true");
-
- // Repeat the longest matching process on the remainder but ensure that the remainder
- // consists only of flags as only flags may be condensed together in this fashion.
- do
- {
- // Match the remainder against the options.
- optionMatcher = pattern.matcher(matchedArg);
- optionMatcher.matches();
-
- matchedOption = optionMatcher.group(1);
- matchedArg = optionMatcher.group(2);
-
- // Check that an option was matched.
- if (matchedOption != null)
- {
- // Get the command line option information for the next matched option.
- optionInfo = optionMap.get(matchedOption);
-
- // Ensure that the next option is a flag or raise an error if not.
- if (optionInfo.expectsArgs)
- {
- parsingErrors.add("Option " + matchedOption + " cannot be combined with flags.\n");
- }
-
- options.put(matchedOption, "true");
- }
- // The remainder could not be matched against a flag it is either an unknown flag
- // or an illegal argument to a flag.
- else
- {
- parsingErrors.add("Illegal argument to a flag in the option " + arg + "\n");
-
- break;
- }
- }
- // Continue until the remainder of the argument has all been matched with flags.
- while (!"".equals(matchedArg));
- }
- // The option is expecting an argument, so store the unmatched portion against it
- // as its argument.
- else
- {
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, matchedArg);
-
- // Store the argument against its option (regardless of its format).
- options.put(matchedOption, matchedArg);
-
- // The argument to this flag has already been supplied to it. Do not swallow the
- // next command line argument as an argument to this flag.
- expectingArgs = false;
- }
- }
- }
- else // No matching option was found.
- {
- // Add this to the list of parsing errors if errors on unkowns is being used.
- if (errorsOnUnknowns)
- {
- parsingErrors.add("Option " + matchedOption + " is not a recognized option.\n");
- }
- }
- }
- // The command line argument did not being with a '-' so it is an argument to the previous flag or it
- // is a free argument.
- else
- {
- // Check if a previous flag is expecting to swallow this next argument as its argument.
- if (expectingArgs)
- {
- // Get the option info for the option waiting for arguments.
- CommandLineOption optionInfo = optionMap.get(optionExpectingArgs);
-
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, arg1);
-
- // Store the argument against its option (regardless of its format).
- options.put(optionExpectingArgs, arg1);
-
- // Clear the expecting args flag now that the argument has been swallowed.
- expectingArgs = false;
- optionExpectingArgs = null;
- }
- // This command line option is not an argument to any option. Add it to the set of 'free' options.
- else
- {
- // Get the option info for the free option, if there is any.
- CommandLineOption optionInfo = optionMap.get(Integer.toString(free));
-
- if (optionInfo != null)
- {
- // Check the arguments format is correct against any specified format.
- checkArgumentFormat(optionInfo, arg1);
- }
-
- // Add to the list of free options.
- options.put(Integer.toString(free), arg1);
-
- // Move on to the next free argument.
- free++;
- }
- }
- }
-
- // Scan through all the specified options to check that all mandatory options have been set and that all flags
- // that were not set are set to false in the set of properties.
- for (CommandLineOption optionInfo : optionMap.values())
- {
- // Check if this is a flag.
- if (!optionInfo.expectsArgs)
- {
- // Check if the flag is not set in the properties and set it to false if so.
- if (!options.containsKey(optionInfo.option))
- {
- options.put(optionInfo.option, "false");
- }
- }
- // Check if this is a mandatory option and was not set.
- else if (optionInfo.mandatory && !options.containsKey(optionInfo.option))
- {
- // Create an error for the missing option.
- parsingErrors.add("Option " + optionInfo.option + " is mandatory but not was not specified.\n");
- }
- }
-
- // Check if there were any errors.
- if (!parsingErrors.isEmpty())
- {
- // Throw an illegal argument exception to signify that there were parsing errors.
- throw new IllegalArgumentException();
- }
-
- // Convert any name/value pairs in the free arguments into properties in the parsed options.
- trailingProperties = takeFreeArgsAsProperties(options, 1);
-
- parsedProperties = options;
-
- return options;
- }
-
- /**
- * If a command line has been parsed, calling this method sets all of its free arguments that were name=value pairs
- * on the specified properties.
- *
- * @param properties The property set to add the name=value pairs to.
- */
- public void addTrailingPairsToProperties(Properties properties)
- {
- if (trailingProperties != null)
- {
- for (Object propKey : trailingProperties.keySet())
- {
- String name = (String) propKey;
- String value = trailingProperties.getProperty(name);
-
- properties.setProperty(name, value);
- }
- }
- }
-
- /**
- * If a command line has been parsed, calling this method sets all of its options that were set to the specified
- * properties.
- *
- * @param properties The property set to the options to.
- */
- public void addOptionsToProperties(Properties properties)
- {
- if (parsedProperties != null)
- {
- for (Object propKey : parsedProperties.keySet())
- {
- String name = (String) propKey;
- String value = parsedProperties.getProperty(name);
-
- // This filters out all trailing items.
- if (!name.matches("^[0-9]+$"))
- {
- properties.setProperty(name, value);
- }
- }
- }
- }
-
- /**
- * Resets this command line parser after it has been used to parse a command line. This method will only need
- * to be called to use this parser a second time which is not likely seeing as a command line is usually only
- * specified once. However, it is exposed as a public method for the rare case where this may be done.
- *
- * <p/>Cleans the internal state of this parser, removing all stored errors and information about the options in
- * force.
- */
- public void reset()
- {
- parsingErrors = new ArrayList<String>();
- parsedProperties = null;
- }
-
- /**
- * Adds the option to list of available command line options.
- *
- * @param option The option to add as an available command line option.
- * @param comment A comment for the option.
- * @param argument The text that appears after the option in the usage string.
- * @param mandatory When true, indicates that this option is mandatory.
- * @param formatRegexp The format that the argument must take, defined as a regular head.
- */
- protected void addOption(String option, String comment, String argument, boolean mandatory, String formatRegexp)
- {
- // Check if usage text has been set in which case this option is expecting arguments.
- boolean expectsArgs = (!((argument == null) || argument.equals("")));
-
- // Add the option to the map of command line options.
- CommandLineOption opt = new CommandLineOption(option, expectsArgs, comment, argument, mandatory, formatRegexp);
- optionMap.put(option, opt);
- }
-
- /**
- * Converts the free arguments into property declarations. After parsing the command line the free arguments
- * are numbered from 1, such that the parsed properties contain values for the keys "1", "2", ... This method
- * converts any free arguments declared using the 'name=value' syntax into properties with key 'name', value
- * 'value'.
- *
- * <p/>For example the comand line:
- * <pre>
- * ... debug=true
- * </pre>
- *
- * <p/>After parsing has properties:
- * <pre>[[1, debug=true]]</pre>
- *
- * <p/>After applying this method the properties are:
- * <pre>[[1, debug=true], [debug, true]]</pre>
- *
- * @param properties The parsed command line properties.
- * @param from The free argument index to convert to properties from.
- *
- * @return The parsed command line properties, with free argument name value pairs too.
- */
- private Properties takeFreeArgsAsProperties(Properties properties, int from)
- {
- Properties result = new Properties();
-
- for (int i = from; true; i++)
- {
- String nextFreeArg = properties.getProperty(Integer.toString(i));
-
- // Terminate the loop once all free arguments have been consumed.
- if (nextFreeArg == null)
- {
- break;
- }
-
- // Split it on the =, strip any whitespace and set it as a system property.
- String[] nameValuePair = nextFreeArg.split("=");
-
- if (nameValuePair.length == 2)
- {
- result.setProperty(nameValuePair[0], nameValuePair[1]);
- }
- }
-
- return result;
- }
-
- /**
- * Checks the format of an argument to an option against its specified regular head format if one has
- * been set. Any errors are added to the list of parsing errors.
- *
- * @param optionInfo The command line option information for the option which is havings its argument checked.
- * @param matchedArg The string argument to the option.
- */
- private void checkArgumentFormat(CommandLineOption optionInfo, String matchedArg)
- {
- // Check if this option enforces a format for its argument.
- if (optionInfo.argumentFormatRegexp != null)
- {
- Pattern pattern = Pattern.compile(optionInfo.argumentFormatRegexp);
- Matcher argumentMatcher = pattern.matcher(matchedArg);
-
- // Check if the argument does not meet its required format.
- if (!argumentMatcher.matches())
- {
- // Create an error for this badly formed argument.
- parsingErrors.add("The argument to option " + optionInfo.option + " does not meet its required format.\n");
- }
- }
- }
-
- /**
- * Holds information about a command line options. This includes what its name is, whether or not it is a flag,
- * whether or not it is mandatory, what its user comment is, what its argument reminder text is and what its
- * regular head format is.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Hold details of a command line option.
- * </table>
- *
- * @author Rupert Smith
- */
- protected class CommandLineOption
- {
- /** Holds the text for the flag to match this argument with. */
- public String option = null;
-
- /** Holds a string describing how to use this command line argument. */
- public String argument = null;
-
- /** Flag that determines whether or not this command line argument can take arguments. */
- public boolean expectsArgs = false;
-
- /** Holds a short comment describing what this command line argument is for. */
- public String comment = null;
-
- /** Flag that determines whether or not this is an mandatory command line argument. */
- public boolean mandatory = false;
-
- /** A regular head describing what format the argument to this option muist have. */
- public String argumentFormatRegexp = null;
-
- /**
- * Create a command line option object that holds specific information about a command line option.
- *
- * @param option The text that matches the option.
- * @param expectsArgs Whether or not the option expects arguments. It is a flag if this is false.
- * @param comment A comment explaining how to use this option.
- * @param argument A short reminder of the format of the argument to this option/
- * @param mandatory Set to true if this option is mandatory.
- * @param formatRegexp The regular head that the argument to this option must meet to be valid.
- */
- public CommandLineOption(String option, boolean expectsArgs, String comment, String argument, boolean mandatory,
- String formatRegexp)
- {
- this.option = option;
- this.expectsArgs = expectsArgs;
- this.comment = comment;
- this.argument = argument;
- this.mandatory = mandatory;
- this.argumentFormatRegexp = formatRegexp;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * CommandLineParser provides a utility for specifying the format of a command line and parsing command lines to ensure
+ * that they fit their specified format. A command line is made up of flags and options, both may be refered to as
+ * options. A flag is an option that does not take an argument (specifying it means it has the value 'true' and not
+ * specifying it means it has the value 'false'). Options must take arguments but they can be set up with defaults so
+ * that they take a default value when not set. Options may be mandatory in wich case it is an error not to specify
+ * them on the command line. Flags are never mandatory because they are implicitly set to false when not specified.
+ *
+ * <p/>Some examples command line are:
+ *
+ * <ul>
+ * <li>This one has two options that expect arguments:
+ * <pre>
+ * cruisecontrol -configfile cruisecontrol.xml -port 9000
+ * </pre>
+ * <li>This has one no-arg flag and two 'free' arguments:
+ * <pre>
+ * zip -r project.zip project/*
+ * </pre>
+ * <li>This one concatenates multiple flags into a single block with only one '-':
+ * <pre>
+ * jar -tvf mytar.tar
+ * </pre>
+ *
+ * <p/>The parsing rules are:
+ *
+ * <ol>
+ * <li>Flags may be combined after a single '-' because they never take arguments. Normally such flags are single letter
+ * flags but this is only a convention and not enforced. Flags of more than one letter are usually specified on their own.
+ * <li>Options expecting arguments must always be on their own.
+ * <li>The argument to an option may be seperated from it by whitespace or appended directly onto the option.
+ * <li>The argument to an option may never begin with a '-' character.
+ * <li>All other arguments not beginning with a '-' character are free arguments that do not belong to any option.
+ * <li>The second or later of a set of duplicate or repeated flags override earlier ones.
+ * <li>Options are matched up to the shortest matching option. This is because of the possibility of having no space
+ * between an option and its argument. This rules out the possibility of using two options where one is an opening
+ * substring of the other. For example, the options "foo" and "foobar" cannot be used on the same command line because
+ * it is not possible to distinguish the argument "-foobar" from being the "foobar" option or the "foo" option with
+ * the "bar" argument.
+ * </ol>
+ *
+ * <p/>By default, unknown options are simply ignored if specified on the command line. This behaviour may be changed
+ * so that the parser reports all unknowns as errors by using the {@link #setErrorsOnUnknowns} method.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept a command line specification.
+ * <tr><td> Parse a command line into properties, validating it against its specification.
+ * <tr><td> Report all errors between a command line and its specification.
+ * <tr><td> Provide a formatted usage string for a command line.
+ * <tr><td> Provide a formatted options in force string for a command line.
+ * <tr><td> Allow errors on unknowns behaviour to be turned on or off.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class CommandLineParser
+{
+ /**
+ * Holds a mapping from command line option names to detailed information about those options.
+ * Use of a tree map ensures that the options are easy to print in alphabetical order as a usage string.
+ * An alternative might be to use a LinkedHashMap to print them in the order they are specified.
+ */
+ private Map<String, CommandLineOption> optionMap = new TreeMap<String, CommandLineOption>();
+
+ /** Holds a list of parsing errors. */
+ private List<String> parsingErrors = new ArrayList<String>();
+
+ /** Holds the regular head matcher to match command line options with. */
+ private Matcher optionMatcher = null;
+
+ /** Holds the parsed command line properties after parsing. */
+ private Properties parsedProperties = null;
+
+ /** Holds any trailing name=value pairs specified in the free arguments. */
+ private Properties trailingProperties = null;
+
+ /** Flag used to indicate that errors should be created for unknown options. False by default. */
+ private boolean errorsOnUnknowns = false;
+
+ /**
+ * Creates a command line options parser from a command line specification. This is passed to this constructor
+ * as an array of arrays of strings. Each array of strings specifies the command line for a single option. A static
+ * array may therefore easily be used to configure the command line parser in a single method call with an easily
+ * readable format.
+ *
+ * <p/>Each array of strings must be 2, 3, 4 or 5 elements long. If any of the last three elements are missing they
+ * are assumed to be null. The elements specify the following parameters:
+ * <ol>
+ * <li>The name of the option without the leading '-'. For example, "file". To specify the format of the 'free'
+ * arguments use the option names "1", "2", ... and so on.
+ * <li>The option comment. A line of text describing the usage of the option. For example, "The file to be processed."
+ * <li>The options argument. This is a very short description of the argument to the option, often a single word
+ * or a reminder as to the arguments format. When this element is null the option is a flag and does not
+ * accept any arguments. For example, "filename" or "(unix | windows)" or null. The actual text specified
+ * is only used to print in the usage message to remind the user of the usage of the option.
+ * <li>The mandatory flag. When set to "true" an option must always be specified. Any other value, including null,
+ * means that the option is mandatory. Flags are always mandatory (see class javadoc for explanation of why) so
+ * this is ignored for flags.
+ * <li>A regular head describing the format that the argument must take. Ignored if null.
+ * </ol>
+ * <p/>An example call to this constructor is:
+ *
+ * <pre>
+ * CommandLineParser commandLine = new CommandLineParser(
+ * new String[][] {{"file", "The file to be processed. ", "filename", "true"},
+ * {"dir", "Directory to store results in. Current dir used if not set.", "out dir"},
+ * {"os", "Operating system EOL format to use.", "(windows | unix)", null, "windows\|unix"},
+ * {"v", "Verbose mode. Prints information about the processing as it goes."},
+ * {"1", "The processing command to run.", "command", "true", "add\|remove\|list"}});
+ * </pre>
+ *
+ * @param config The configuration as an array of arrays of strings.
+ */
+ public CommandLineParser(String[][] config)
+ {
+ // Loop through all the command line option specifications creating details for each in the options map.
+ for (String[] nextOptionSpec : config)
+ {
+ addOption(nextOptionSpec[0], nextOptionSpec[1], (nextOptionSpec.length > 2) ? nextOptionSpec[2] : null,
+ (nextOptionSpec.length > 3) && ("true".equals(nextOptionSpec[3])),
+ (nextOptionSpec.length > 4) ? nextOptionSpec[4] : null);
+ }
+ }
+
+ /**
+ * Extracts all name=value pairs from the command line, sets them all as system properties and also returns
+ * a map of properties containing them.
+ *
+ * @param args The command line.
+ * @param commandLine The command line parser.
+ * @param properties The properties object to inject all parsed properties into (optional may be <tt>null</tt>).
+ *
+ * @return A set of properties containing all name=value pairs from the command line.
+ */
+ public static Properties processCommandLine(String[] args, CommandLineParser commandLine, Properties properties)
+ {
+ // Capture the command line arguments or display errors and correct usage and then exit.
+ Properties options = null;
+
+ try
+ {
+ options = commandLine.parseCommandLine(args);
+
+ // Add all the command line options and trailing settings to properties if the optional properties object
+ // to copy them into has been set.
+ if (properties != null)
+ {
+ commandLine.addTrailingPairsToProperties(properties);
+ commandLine.addOptionsToProperties(properties);
+ }
+ }
+ catch (IllegalArgumentException e)
+ {
+ System.out.println(commandLine.getErrors());
+ System.out.println(commandLine.getUsage());
+ System.exit(1);
+ }
+
+ return options;
+ }
+
+ /**
+ * Lists all the parsing errors from the most recent parsing in a string.
+ *
+ * @return All the parsing errors from the most recent parsing.
+ */
+ public String getErrors()
+ {
+ // Return the empty string if there are no errors.
+ if (parsingErrors.isEmpty())
+ {
+ return "";
+ }
+
+ // Concatenate all the parsing errors together.
+ String result = "";
+
+ for (String s : parsingErrors)
+ {
+ result += s;
+ }
+
+ return result;
+ }
+
+ /**
+ * Lists the properties set from the most recent parsing or an empty string if no parsing has been done yet.
+ *
+ * @return The properties set from the most recent parsing or an empty string if no parsing has been done yet.
+ */
+ public String getOptionsInForce()
+ {
+ // Check if there are no properties to report and return and empty string if so.
+ if (parsedProperties == null)
+ {
+ return "";
+ }
+
+ // List all the properties.
+ String result = "Options in force:\n";
+
+ for (Map.Entry<Object, Object> property : parsedProperties.entrySet())
+ {
+ result += property.getKey() + " = " + property.getValue() + "\n";
+ }
+
+ return result;
+ }
+
+ /**
+ * Generates a usage string consisting of the name of each option and each options argument description and
+ * comment.
+ *
+ * @return A usage string for all the options.
+ */
+ public String getUsage()
+ {
+ String result = "Options:\n";
+
+ int optionWidth = 0;
+ int argumentWidth = 0;
+
+ // Calculate the column widths required for aligned layout.
+ for (CommandLineOption optionInfo : optionMap.values())
+ {
+ int oWidth = optionInfo.option.length();
+ int aWidth = (optionInfo.argument != null) ? (optionInfo.argument.length()) : 0;
+
+ optionWidth = (oWidth > optionWidth) ? oWidth : optionWidth;
+ argumentWidth = (aWidth > argumentWidth) ? aWidth : argumentWidth;
+ }
+
+ // Print usage on each of the command line options.
+ for (CommandLineOption optionInfo : optionMap.values())
+ {
+ String argString = ((optionInfo.argument != null) ? (optionInfo.argument) : "");
+ String optionString = optionInfo.option;
+
+ argString = rightPad(argString, " ", argumentWidth);
+ optionString = rightPad(optionString, " ", optionWidth);
+
+ result += "-" + optionString + " " + argString + " " + optionInfo.comment + "\n";
+ }
+
+ return result;
+ }
+
+ /**
+ * Right pads a string with a given string to a given size. This method will repeat the padder string as many
+ * times as is necessary until the exact specified size is reached. If the specified size is less than the size
+ * of the original string then the original string is returned unchanged.
+ *
+ * <pre>
+ * Example1 - original string "cat", padder string "white", size 8 gives "catwhite".
+ * Example2 - original string "cat", padder string "white", size 15 gives "catwhitewhitewh".
+ * Example3 - original string "cat", padder string "white", size 2 gives "cat".
+ * </pre>
+ *
+ * @param stringToPad The original string.
+ * @param padder The string to pad onto the original string.
+ * @param size The required size of the new string.
+ *
+ * @return The newly padded string.
+ */
+ public static String rightPad(String stringToPad, String padder, int size)
+ {
+ if (padder.length() == 0)
+ {
+ return stringToPad;
+ }
+
+ StringBuffer strb = new StringBuffer(stringToPad);
+ StringCharacterIterator sci = new StringCharacterIterator(padder);
+
+ while (strb.length() < size)
+ {
+ for (char ch = sci.first(); ch != CharacterIterator.DONE; ch = sci.next())
+ {
+ if (strb.length() < size)
+ {
+ strb.append(String.valueOf(ch));
+ }
+ }
+ }
+
+ return strb.toString();
+ }
+
+ /**
+ * Control the behaviour of the errors on unkowns reporting. When turned on this reports all unkowns options
+ * as errors. When turned off, all unknowns are simply ignored.
+ *
+ * @param errors The setting of the errors on unkown flag. True to turn it on.
+ */
+ public void setErrorsOnUnknowns(boolean errors)
+ {
+ errorsOnUnknowns = errors;
+ }
+
+ /**
+ * Parses a set of command line arguments into a set of properties, keyed by the argument flag. The free arguments
+ * are keyed by integers as strings starting at "1" and then "2", ... and so on.
+ *
+ * <p/>See the class level comment for a description of the parsing rules.
+ *
+ * @param args The command line arguments.
+ *
+ * @return The arguments as a set of properties.
+ *
+ * @throws IllegalArgumentException If the command line cannot be parsed against its specification. If this exception
+ * is thrown a call to {@link #getErrors} will provide a diagnostic of the command
+ * line errors.
+ */
+ public Properties parseCommandLine(String[] args) throws IllegalArgumentException
+ {
+ Properties options = new Properties();
+
+ // Used to keep count of the current 'free' argument.
+ int free = 1;
+
+ // Used to indicate that the most recently parsed option is expecting arguments.
+ boolean expectingArgs = false;
+
+ // The option that is expecting arguments from the next element of the command line.
+ String optionExpectingArgs = null;
+
+ // Used to indicate that the most recently parsed option is a duplicate and should be ignored.
+ // boolean ignore = false;
+
+ // Create the regular head matcher for the command line options.
+ String regexp = "^(";
+ int optionsAdded = 0;
+
+ for (Iterator<String> i = optionMap.keySet().iterator(); i.hasNext();)
+ {
+ String nextOption = i.next();
+
+ // Check that the option is not a free argument definition.
+ boolean notFree = false;
+
+ try
+ {
+ Integer.parseInt(nextOption);
+ }
+ catch (NumberFormatException e)
+ {
+ notFree = true;
+ }
+
+ // Add the option to the regular head matcher if it is not a free argument definition.
+ if (notFree)
+ {
+ regexp += nextOption + (i.hasNext() ? "|" : "");
+ optionsAdded++;
+ }
+ }
+
+ // There has to be more that one option in the regular head or else the compiler complains that the close
+ // cannot be nullable if the '?' token is used to make the matched option string optional.
+ regexp += ")" + ((optionsAdded > 0) ? "?" : "") + "(.*)";
+ Pattern pattern = Pattern.compile(regexp);
+
+ // Loop through all the command line arguments.
+ for (String arg1 : args)
+ {
+ // Check if the next command line argument begins with a '-' character and is therefore the start of
+ // an option.
+ if (arg1.startsWith("-"))
+ {
+ // Extract the value of the option without the leading '-'.
+ String arg = arg1.substring(1);
+
+ // Match up to the longest matching option.
+ optionMatcher = pattern.matcher(arg);
+ optionMatcher.matches();
+
+ String matchedOption = optionMatcher.group(1);
+
+ // Match any argument directly appended onto the longest matching option.
+ String matchedArg = optionMatcher.group(2);
+
+ // Check that a known option was matched.
+ if ((matchedOption != null) && !"".equals(matchedOption))
+ {
+ // Get the command line option information for the matched option.
+ CommandLineOption optionInfo = optionMap.get(matchedOption);
+
+ // Check if this option is expecting arguments.
+ if (optionInfo.expectsArgs)
+ {
+ // The option is expecting arguments so swallow the next command line argument as an
+ // argument to this option.
+ expectingArgs = true;
+ optionExpectingArgs = matchedOption;
+
+ // In the mean time set this options argument to the empty string in case no argument is ever
+ // supplied.
+ // options.put(matchedOption, "");
+ }
+
+ // Check if the option was matched on its own and is a flag in which case set that flag.
+ if ("".equals(matchedArg) && !optionInfo.expectsArgs)
+ {
+ options.put(matchedOption, "true");
+ }
+ // The option was matched as a substring with its argument appended to it or is a flag that is
+ // condensed together with other flags.
+ else if (!"".equals(matchedArg))
+ {
+ // Check if the option is a flag and therefore is allowed to be condensed together
+ // with other flags.
+ if (!optionInfo.expectsArgs)
+ {
+ // Set the first matched flag.
+ options.put(matchedOption, "true");
+
+ // Repeat the longest matching process on the remainder but ensure that the remainder
+ // consists only of flags as only flags may be condensed together in this fashion.
+ do
+ {
+ // Match the remainder against the options.
+ optionMatcher = pattern.matcher(matchedArg);
+ optionMatcher.matches();
+
+ matchedOption = optionMatcher.group(1);
+ matchedArg = optionMatcher.group(2);
+
+ // Check that an option was matched.
+ if (matchedOption != null)
+ {
+ // Get the command line option information for the next matched option.
+ optionInfo = optionMap.get(matchedOption);
+
+ // Ensure that the next option is a flag or raise an error if not.
+ if (optionInfo.expectsArgs)
+ {
+ parsingErrors.add("Option " + matchedOption + " cannot be combined with flags.\n");
+ }
+
+ options.put(matchedOption, "true");
+ }
+ // The remainder could not be matched against a flag it is either an unknown flag
+ // or an illegal argument to a flag.
+ else
+ {
+ parsingErrors.add("Illegal argument to a flag in the option " + arg + "\n");
+
+ break;
+ }
+ }
+ // Continue until the remainder of the argument has all been matched with flags.
+ while (!"".equals(matchedArg));
+ }
+ // The option is expecting an argument, so store the unmatched portion against it
+ // as its argument.
+ else
+ {
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, matchedArg);
+
+ // Store the argument against its option (regardless of its format).
+ options.put(matchedOption, matchedArg);
+
+ // The argument to this flag has already been supplied to it. Do not swallow the
+ // next command line argument as an argument to this flag.
+ expectingArgs = false;
+ }
+ }
+ }
+ else // No matching option was found.
+ {
+ // Add this to the list of parsing errors if errors on unkowns is being used.
+ if (errorsOnUnknowns)
+ {
+ parsingErrors.add("Option " + matchedOption + " is not a recognized option.\n");
+ }
+ }
+ }
+ // The command line argument did not being with a '-' so it is an argument to the previous flag or it
+ // is a free argument.
+ else
+ {
+ // Check if a previous flag is expecting to swallow this next argument as its argument.
+ if (expectingArgs)
+ {
+ // Get the option info for the option waiting for arguments.
+ CommandLineOption optionInfo = optionMap.get(optionExpectingArgs);
+
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, arg1);
+
+ // Store the argument against its option (regardless of its format).
+ options.put(optionExpectingArgs, arg1);
+
+ // Clear the expecting args flag now that the argument has been swallowed.
+ expectingArgs = false;
+ optionExpectingArgs = null;
+ }
+ // This command line option is not an argument to any option. Add it to the set of 'free' options.
+ else
+ {
+ // Get the option info for the free option, if there is any.
+ CommandLineOption optionInfo = optionMap.get(Integer.toString(free));
+
+ if (optionInfo != null)
+ {
+ // Check the arguments format is correct against any specified format.
+ checkArgumentFormat(optionInfo, arg1);
+ }
+
+ // Add to the list of free options.
+ options.put(Integer.toString(free), arg1);
+
+ // Move on to the next free argument.
+ free++;
+ }
+ }
+ }
+
+ // Scan through all the specified options to check that all mandatory options have been set and that all flags
+ // that were not set are set to false in the set of properties.
+ for (CommandLineOption optionInfo : optionMap.values())
+ {
+ // Check if this is a flag.
+ if (!optionInfo.expectsArgs)
+ {
+ // Check if the flag is not set in the properties and set it to false if so.
+ if (!options.containsKey(optionInfo.option))
+ {
+ options.put(optionInfo.option, "false");
+ }
+ }
+ // Check if this is a mandatory option and was not set.
+ else if (optionInfo.mandatory && !options.containsKey(optionInfo.option))
+ {
+ // Create an error for the missing option.
+ parsingErrors.add("Option " + optionInfo.option + " is mandatory but not was not specified.\n");
+ }
+ }
+
+ // Check if there were any errors.
+ if (!parsingErrors.isEmpty())
+ {
+ // Throw an illegal argument exception to signify that there were parsing errors.
+ throw new IllegalArgumentException();
+ }
+
+ // Convert any name/value pairs in the free arguments into properties in the parsed options.
+ trailingProperties = takeFreeArgsAsProperties(options, 1);
+
+ parsedProperties = options;
+
+ return options;
+ }
+
+ /**
+ * If a command line has been parsed, calling this method sets all of its free arguments that were name=value pairs
+ * on the specified properties.
+ *
+ * @param properties The property set to add the name=value pairs to.
+ */
+ public void addTrailingPairsToProperties(Properties properties)
+ {
+ if (trailingProperties != null)
+ {
+ for (Object propKey : trailingProperties.keySet())
+ {
+ String name = (String) propKey;
+ String value = trailingProperties.getProperty(name);
+
+ properties.setProperty(name, value);
+ }
+ }
+ }
+
+ /**
+ * If a command line has been parsed, calling this method sets all of its options that were set to the specified
+ * properties.
+ *
+ * @param properties The property set to the options to.
+ */
+ public void addOptionsToProperties(Properties properties)
+ {
+ if (parsedProperties != null)
+ {
+ for (Object propKey : parsedProperties.keySet())
+ {
+ String name = (String) propKey;
+ String value = parsedProperties.getProperty(name);
+
+ // This filters out all trailing items.
+ if (!name.matches("^[0-9]+$"))
+ {
+ properties.setProperty(name, value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Resets this command line parser after it has been used to parse a command line. This method will only need
+ * to be called to use this parser a second time which is not likely seeing as a command line is usually only
+ * specified once. However, it is exposed as a public method for the rare case where this may be done.
+ *
+ * <p/>Cleans the internal state of this parser, removing all stored errors and information about the options in
+ * force.
+ */
+ public void reset()
+ {
+ parsingErrors = new ArrayList<String>();
+ parsedProperties = null;
+ }
+
+ /**
+ * Adds the option to list of available command line options.
+ *
+ * @param option The option to add as an available command line option.
+ * @param comment A comment for the option.
+ * @param argument The text that appears after the option in the usage string.
+ * @param mandatory When true, indicates that this option is mandatory.
+ * @param formatRegexp The format that the argument must take, defined as a regular head.
+ */
+ protected void addOption(String option, String comment, String argument, boolean mandatory, String formatRegexp)
+ {
+ // Check if usage text has been set in which case this option is expecting arguments.
+ boolean expectsArgs = (!((argument == null) || argument.equals("")));
+
+ // Add the option to the map of command line options.
+ CommandLineOption opt = new CommandLineOption(option, expectsArgs, comment, argument, mandatory, formatRegexp);
+ optionMap.put(option, opt);
+ }
+
+ /**
+ * Converts the free arguments into property declarations. After parsing the command line the free arguments
+ * are numbered from 1, such that the parsed properties contain values for the keys "1", "2", ... This method
+ * converts any free arguments declared using the 'name=value' syntax into properties with key 'name', value
+ * 'value'.
+ *
+ * <p/>For example the comand line:
+ * <pre>
+ * ... debug=true
+ * </pre>
+ *
+ * <p/>After parsing has properties:
+ * <pre>[[1, debug=true]]</pre>
+ *
+ * <p/>After applying this method the properties are:
+ * <pre>[[1, debug=true], [debug, true]]</pre>
+ *
+ * @param properties The parsed command line properties.
+ * @param from The free argument index to convert to properties from.
+ *
+ * @return The parsed command line properties, with free argument name value pairs too.
+ */
+ private Properties takeFreeArgsAsProperties(Properties properties, int from)
+ {
+ Properties result = new Properties();
+
+ for (int i = from; true; i++)
+ {
+ String nextFreeArg = properties.getProperty(Integer.toString(i));
+
+ // Terminate the loop once all free arguments have been consumed.
+ if (nextFreeArg == null)
+ {
+ break;
+ }
+
+ // Split it on the =, strip any whitespace and set it as a system property.
+ String[] nameValuePair = nextFreeArg.split("=");
+
+ if (nameValuePair.length == 2)
+ {
+ result.setProperty(nameValuePair[0], nameValuePair[1]);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Checks the format of an argument to an option against its specified regular head format if one has
+ * been set. Any errors are added to the list of parsing errors.
+ *
+ * @param optionInfo The command line option information for the option which is havings its argument checked.
+ * @param matchedArg The string argument to the option.
+ */
+ private void checkArgumentFormat(CommandLineOption optionInfo, String matchedArg)
+ {
+ // Check if this option enforces a format for its argument.
+ if (optionInfo.argumentFormatRegexp != null)
+ {
+ Pattern pattern = Pattern.compile(optionInfo.argumentFormatRegexp);
+ Matcher argumentMatcher = pattern.matcher(matchedArg);
+
+ // Check if the argument does not meet its required format.
+ if (!argumentMatcher.matches())
+ {
+ // Create an error for this badly formed argument.
+ parsingErrors.add("The argument to option " + optionInfo.option + " does not meet its required format.\n");
+ }
+ }
+ }
+
+ /**
+ * Holds information about a command line options. This includes what its name is, whether or not it is a flag,
+ * whether or not it is mandatory, what its user comment is, what its argument reminder text is and what its
+ * regular head format is.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Hold details of a command line option.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+ protected class CommandLineOption
+ {
+ /** Holds the text for the flag to match this argument with. */
+ public String option = null;
+
+ /** Holds a string describing how to use this command line argument. */
+ public String argument = null;
+
+ /** Flag that determines whether or not this command line argument can take arguments. */
+ public boolean expectsArgs = false;
+
+ /** Holds a short comment describing what this command line argument is for. */
+ public String comment = null;
+
+ /** Flag that determines whether or not this is an mandatory command line argument. */
+ public boolean mandatory = false;
+
+ /** A regular head describing what format the argument to this option muist have. */
+ public String argumentFormatRegexp = null;
+
+ /**
+ * Create a command line option object that holds specific information about a command line option.
+ *
+ * @param option The text that matches the option.
+ * @param expectsArgs Whether or not the option expects arguments. It is a flag if this is false.
+ * @param comment A comment explaining how to use this option.
+ * @param argument A short reminder of the format of the argument to this option/
+ * @param mandatory Set to true if this option is mandatory.
+ * @param formatRegexp The regular head that the argument to this option must meet to be valid.
+ */
+ public CommandLineOption(String option, boolean expectsArgs, String comment, String argument, boolean mandatory,
+ String formatRegexp)
+ {
+ this.option = option;
+ this.expectsArgs = expectsArgs;
+ this.comment = comment;
+ this.argument = argument;
+ this.mandatory = mandatory;
+ this.argumentFormatRegexp = formatRegexp;
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java
index cabbf7869a..14de96d165 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ContextualProperties.java
@@ -1,494 +1,494 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * ContextualProperties is an extension of {@link java.util.Properties} that automatically selects properties based on an
- * environment parameter (defined by the system property {@link #ENV_SYS_PROPERTY}), the name of a class, plus a modifier
- * (which can be used to name a method of a class) and a property key. It also supports the definition of arrays of
- * property values using indexes. The properties are searched in the following order until a match is found:
- *
- * <ol>
- * <li>environment + class name with package name + modifier + key
- * <li>environment + class name with package name + key
- * <li>environment + key
- * <li>class name with package name + modifier + key
- * <li>class name with package name + key
- * <li>key
- * </ol>
- *
- * <p>To create arrays of property values add index numbers onto the end of the property keys. An array of string values
- * will be created with the elements of the array set to the value of the property at the matching index. Ideally the
- * index values will be contiguous, starting at 0. This does not need to be the case however. If an array definition
- * begins at index n, and ends at index m, Then an array big enough to hold m + 1 elements will be created and populated
- * with values from n to m. Values before n and any missing values between n and m will be null in the array.
- *
- * <p>To give an example, suppose you have two different environments 'DEVELOPMENT' and 'PRODUCTION' and they each need
- * the same properties but set to different values for each environment and some properties the same in both, you could
- * create a properties file like:
- *
- * <p><code>
- * # Project configuration properties file.<br/>
- * <br/>
- * # These properties are environment specific.<br/>
- * DEVELOPMENT.debug=true<br/>
- * PRODUCTION.debug=false<br/>
- * <br/>
- * # Always debug MyClass in all environments but not the myMethod method.<br/>
- * MyClass.debug=true<br/>
- * MyClass.myMethod.debug=false<br/>
- * <br/>
- * # Set up an array of my ten favourite animals. Leave elements 3 to 8 as null as I haven't decided on them yet.<br/>
- * animals.0=cat<br/>
- * animals.1=dog<br/>
- * animals.2=elephant<br/>
- * animals.9=lion<br/>
- * <br/>
- * # This is a default value that will be used when the environment is not known.<br/>
- * debug=false<br/>
- * </code>
- *
- * <p>The most specific definition of a property is searched for first moving out to the most general. This allows
- * general property defaults to be set and then overiden for specific uses by some classes and modifiers.
- *
- * <p>A ContextualProperties object can be loaded in the same way as a java.utils.Properties. A recommended way to do
- * this that does not assume that the properties file is a file (it could be in a jar) is to load the properties from the
- * url for the resource lookup up on the classpath:
- *
- * <p><code>
- * Properties configProperties = new ContextualProperties();<br/>
- * configProperties.load(this.getClass().getClassLoader().getResourceAsStream("config.properties"));<br/>
- * </code>
- *
- * <p>EnvironmentProperties will load the 'DEVELOPMENT.debug' property or 'PROUCTION.debug' property based on the setting
- * of the system environment property. If a matching property for the environment cannot be found then the simple property
- * name without the environment pre-pended onto it will be used instead. This 'use of default environments' behaviour is
- * turned on initially but it can be disabled by calling the {@link #useDefaultEnvironments} method.
- *
- * <p>When a property matching a key cannot be found then the property accessor methods will always return null. If a
- * default value for a property exists but the 'use of default environments' behavious prevents it being used then the
- * accessor methods will return null.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Automatically select properties dependant on environment, class name and modifier as well as property key.
- * <tr><td> Convert indexed properties into arrays.
- * </table>
- *
- * @author Rupert Smith
- */
-public class ContextualProperties extends ParsedProperties
-{
- /** The name of the system property that is used to define the environment. */
- public static final String ENV_SYS_PROPERTY = "environment";
-
- /**
- * <p>Holds the iteration count down order.
- *
- * <p>If e = 4, b = 2, m = 1 then the iteration order or i is 7,6,4 and then if using environment defaults 3,2,0
- * where the accessor key is:
- * (i & e != 0 ? environment : "") + (i & b != 0 ? base : "") + (1 + m != 0 ? modifier : "") + key
- *
- * <p>In other words the presence or otherwise of the three least significant bits when counting down from 7
- * specifies which of the environment, base and modifier are to be included in the key where the environment, base
- * and modifier stand for the bits in positions 2, 1 and 0. The numbers 5 and 1 are missed out of the count because
- * they stand for the case where the modifier is used without the base which is not done.
- */
- private static final int[] ORDER = new int[] { 7, 6, 4, 3, 2, 0 };
-
- /**
- * Defines the point in the iteration count order below which the 'use environment defaults' feature is being used.
- */
- private static final int ENVIRONMENT_DEFAULTS_CUTOFF = 4;
-
- /** Defines the bit representation for the environment in the key ordering. See {@link #ORDER}. */
- private static final int E = 4;
-
- /** Defines the bit representation for the base in the key ordering. See {@link #ORDER}. */
- private static final int B = 2;
-
- /** Defines the bit representation for the modifier in the key ordering. See {@link #ORDER}. */
- private static final int M = 1;
-
- /** Used to hold the value of the environment system property. */
- private String environment;
-
- /** Used to indicate that the 'use of defaults' behaviour should be used. */
- private boolean useDefaults = true;
-
- /** Used to hold all the array properties. This is a mapping from property names to ArrayLists of Strings. */
- protected Map arrayProperties = new HashMap();
-
- /**
- * Default constructor that builds a ContextualProperties that uses environment defaults.
- */
- public ContextualProperties()
- {
- super();
-
- // Keep the value of the system environment property.
- environment = System.getProperty(ENV_SYS_PROPERTY);
- }
-
- /**
- * Creates a ContextualProperties that uses environment defaults and is initialized with the specified properties.
- *
- * @param props The properties to initialize this with.
- */
- public ContextualProperties(Properties props)
- {
- super(props);
-
- // Keep the value of the system environment property.
- environment = System.getProperty(ENV_SYS_PROPERTY);
-
- // Extract any array properties as arrays.
- createArrayProperties();
- }
-
- /**
- * Parses an input stream as properties.
- *
- * @param inStream The input stream to read the properties from.
- *
- * @exception IOException If there is an IO error during reading from the input stream.
- */
- public void load(InputStream inStream) throws IOException
- {
- super.load(inStream);
-
- // Extract any array properties as arrays.
- createArrayProperties();
- }
-
- /**
- * Tells this environment aware properties object whether it should use default environment properties without a
- * pre-pended environment when a property for the current environment cannot be found.
- *
- * @param flag True to use defaults, false to not use defaults.
- */
- public void useDefaultEnvironments(boolean flag)
- {
- useDefaults = flag;
- }
-
- /**
- * Looks up a property value relative to the environment, callers class and method. The default environment will be
- * checked for a matching property if defaults are being used. In order to work out the callers class and method this
- * method throws an exception and then searches one level up its stack frames.
- *
- * @param key The property key.
- *
- * @return The value of this property searching from the most specific definition (environment, class, method, key)
- * to the most general (key only), unless use of default environments is turned off in which case the most general
- * proeprty searched is (environment, key).
- */
- public String getProperty(String key)
- {
- // Try to get the callers class name and method name by examing the stack.
- String className = null;
- String methodName = null;
-
- // Java 1.4 onwards only.
- /*try
- {
- throw new Exception();
- }
- catch (Exception e)
- {
- StackTraceElement[] stack = e.getStackTrace();
-
- // Check that the stack trace contains at least two elements, one for this method and one for the caller.
- if (stack.length >= 2)
- {
- className = stack[1].getClassName();
- methodName = stack[1].getMethodName();
- }
- }*/
-
- // Java 1.5 onwards only.
- StackTraceElement[] stack = Thread.currentThread().getStackTrace();
-
- // Check that the stack trace contains at least two elements, one for this method and one for the caller.
- if (stack.length >= 2)
- {
- className = stack[1].getClassName();
- methodName = stack[1].getMethodName();
- }
-
- // Java 1.3 and before? Not sure, some horrible thing that parses the text spat out by printStackTrace?
-
- return getProperty(className, methodName, key);
- }
-
- /**
- * Looks up a property value relative to the environment, base class and modifier. The default environment will be
- * checked for a matching property if defaults are being used.
- *
- * @param base An object of the class to retrieve properties relative to.
- * @param modifier The modifier (which may stand for a method of the class).
- * @param key The property key.
- *
- * @return The value of this property searching from the most specific definition (environment, class, modifier, key)
- * to the most general (key only), unless use of default environments is turned off in which case the most general
- * property searched is (environment, key).
- */
- public String getProperty(Object base, String modifier, String key)
- {
- return getProperty(base.getClass().getName(), modifier, key);
- }
-
- /**
- * Looks up a property value relative to the environment, base class and modifier. The default environment will be
- * checked for a matching property if defaults are being used.
- *
- * @param base The name of the class to retrieve properties relative to.
- * @param modifier The modifier (which may stand for a method of the class).
- * @param key The property key.
- *
- * @return The value of this property searching from the most specific definition (environment, class, modifier, key)
- * to the most general (key only), unless use of default environments is turned off in which case the most general
- * property searched is (environment, key).
- */
- public String getProperty(String base, String modifier, String key)
- {
- String result = null;
-
- // Loop over the key orderings, from the most specific to the most general, until a matching value is found.
- for (Iterator i = getKeyIterator(base, modifier, key); i.hasNext();)
- {
- String nextKey = (String) i.next();
-
- result = super.getProperty(nextKey);
-
- if (result != null)
- {
- break;
- }
- }
-
- return result;
- }
-
- /**
- * Looks up an array property value relative to the environment, callers class and method. The default environment
- * will be checked for a matching array property if defaults are being used. In order to work out the callers class
- * and method this method throws an exception and then searches one level up its stack frames.
- *
- * @param key The property key.
- *
- * @return The array value of this indexed property searching from the most specific definition (environment, class,
- * method, key) to the most general (key only), unless use of default environments is turned off in which
- * case the most general proeprty searched is (environment, key).
- */
- public String[] getProperties(String key)
- {
- // Try to get the callers class name and method name by throwing an exception an searching the stack frames.
- String className = null;
- String methodName = null;
-
- /* Java 1.4 onwards only.
- try {
- throw new Exception();
- } catch (Exception e) {
- StackTraceElement[] stack = e.getStackTrace();
- // Check that the stack trace contains at least two elements, one for this method and one for the caller.
- if (stack.length >= 2) {
- className = stack[1].getClassName();
- methodName = stack[1].getMethodName();
- }
- }*/
- return getProperties(className, methodName, key);
- }
-
- /**
- * Looks up an array property value relative to the environment, base class and modifier. The default environment will
- * be checked for a matching array property if defaults are being used.
- *
- * @param base An object of the class to retrieve properties relative to.
- * @param modifier The modifier (which may stand for a method of the class).
- * @param key The property key.
- *
- * @return The array value of this indexed property searching from the most specific definition (environment, class,
- * modifier, key) to the most general (key only), unless use of default environments is turned off in which
- * case the most general proeprty searched is (environment, key).
- */
- public String[] getProperties(Object base, String modifier, String key)
- {
- return getProperties(base.getClass().getName(), modifier, key);
- }
-
- /**
- * Looks up an array property value relative to the environment, base class and modifier. The default environment will
- * be checked for a matching array property if defaults are being used.
- *
- * @param base The name of the class to retrieve properties relative to.
- * @param modifier The modifier (which may stand for a method of the class).
- * @param key The property key.
- *
- * @return The array value of this indexed property searching from the most specific definition (environment, class,
- * modifier, key) to the most general (key only), unless use of default environments is turned off in which
- * case the most general property searched is (environment, key).
- */
- public String[] getProperties(String base, String modifier, String key)
- {
- String[] result = null;
-
- // Loop over the key orderings, from the most specific to the most general, until a matching value is found.
- for (Iterator i = getKeyIterator(base, modifier, key); i.hasNext();)
- {
- String nextKey = (String) i.next();
- ArrayList arrayList = (ArrayList) arrayProperties.get(nextKey);
-
- if (arrayList != null)
- {
- result = (String[]) arrayList.toArray(new String[] {});
-
- break;
- }
- }
-
- return result;
- }
-
- /**
- * For a given environment, base, modifier and key and setting of the use of default environments feature this
- * generates an iterator that walks over the order in which to try and access properties.
- *
- * <p>See the {@link #ORDER} constant for an explanation of how the key ordering is generated.
- *
- * @param base The name of the class to retrieve properties relative to.
- * @param modifier The modifier (which may stand for a method of the class).
- * @param key The property key.
- *
- * @return An Iterator over String keys defining the order in which properties should be accessed.
- */
- protected Iterator getKeyIterator(final String base, final String modifier, final String key)
- {
- return new Iterator()
- {
- // The key ordering count always begins at the start of the ORDER array.
- private int i = 0;
-
- public boolean hasNext()
- {
- return (useDefaults ? ((i < ORDER.length) && (ORDER[i] > ENVIRONMENT_DEFAULTS_CUTOFF))
- : (i < ORDER.length));
- }
-
- public Object next()
- {
- // Check that there is a next element and return null if not.
- if (!hasNext())
- {
- return null;
- }
-
- // Get the next ordering count.
- int o = ORDER[i];
-
- // Do bit matching on the count to choose which elements to include in the key.
- String result =
- (((o & E) != 0) ? (environment + ".") : "") + (((o & B) != 0) ? (base + ".") : "")
- + (((o & M) != 0) ? (modifier + ".") : "") + key;
-
- // Increment the iterator to get the next key on the next call.
- i++;
-
- return result;
- }
-
- public void remove()
- {
- // This method is not supported.
- throw new UnsupportedOperationException("remove() is not supported on this key order iterator as "
- + "the ordering cannot be changed");
- }
- };
- }
-
- /**
- * Scans all the properties in the parent Properties object and creates arrays for any array property definitions.
- *
- * <p>Array properties are defined with indexes. For example:
- *
- * <p><code>
- * property.1=one<br/>
- * property.2=two<br/>
- * property.3=three<br/>
- * </code>
- *
- * <p>Note that these properties will be stored as the 'empty string' or "" property array.
- *
- * <p><code>
- * .1=one<br/>
- * 2=two<br/>
- * </code>
- */
- protected void createArrayProperties()
- {
- // Scan through all defined properties.
- for (Object o : keySet())
- {
- String key = (String) o;
- String value = super.getProperty(key);
-
- // Split the property key into everything before the last '.' and after it.
- int lastDotIndex = key.lastIndexOf('.');
- String keyEnding = key.substring(lastDotIndex + 1, key.length());
- String keyStart = key.substring(0, (lastDotIndex == -1) ? 0 : lastDotIndex);
-
- // Check if the property key ends in an integer, in which case it is an array property.
- int index = 0;
-
- try
- {
- index = Integer.parseInt(keyEnding);
- }
- // The ending is not an integer so its not an array.
- catch (NumberFormatException e)
- {
- // Scan the next property.
- continue;
- }
-
- // Check if an array property already exists for this base name and create one if not.
- ArrayList propArray = (ArrayList) arrayProperties.get(keyStart);
-
- if (propArray == null)
- {
- propArray = new ArrayList();
- arrayProperties.put(keyStart, propArray);
- }
-
- // Add the new property value to the array property for the index.
- propArray.set(index, value);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * ContextualProperties is an extension of {@link java.util.Properties} that automatically selects properties based on an
+ * environment parameter (defined by the system property {@link #ENV_SYS_PROPERTY}), the name of a class, plus a modifier
+ * (which can be used to name a method of a class) and a property key. It also supports the definition of arrays of
+ * property values using indexes. The properties are searched in the following order until a match is found:
+ *
+ * <ol>
+ * <li>environment + class name with package name + modifier + key
+ * <li>environment + class name with package name + key
+ * <li>environment + key
+ * <li>class name with package name + modifier + key
+ * <li>class name with package name + key
+ * <li>key
+ * </ol>
+ *
+ * <p>To create arrays of property values add index numbers onto the end of the property keys. An array of string values
+ * will be created with the elements of the array set to the value of the property at the matching index. Ideally the
+ * index values will be contiguous, starting at 0. This does not need to be the case however. If an array definition
+ * begins at index n, and ends at index m, Then an array big enough to hold m + 1 elements will be created and populated
+ * with values from n to m. Values before n and any missing values between n and m will be null in the array.
+ *
+ * <p>To give an example, suppose you have two different environments 'DEVELOPMENT' and 'PRODUCTION' and they each need
+ * the same properties but set to different values for each environment and some properties the same in both, you could
+ * create a properties file like:
+ *
+ * <p><code>
+ * # Project configuration properties file.<br/>
+ * <br/>
+ * # These properties are environment specific.<br/>
+ * DEVELOPMENT.debug=true<br/>
+ * PRODUCTION.debug=false<br/>
+ * <br/>
+ * # Always debug MyClass in all environments but not the myMethod method.<br/>
+ * MyClass.debug=true<br/>
+ * MyClass.myMethod.debug=false<br/>
+ * <br/>
+ * # Set up an array of my ten favourite animals. Leave elements 3 to 8 as null as I haven't decided on them yet.<br/>
+ * animals.0=cat<br/>
+ * animals.1=dog<br/>
+ * animals.2=elephant<br/>
+ * animals.9=lion<br/>
+ * <br/>
+ * # This is a default value that will be used when the environment is not known.<br/>
+ * debug=false<br/>
+ * </code>
+ *
+ * <p>The most specific definition of a property is searched for first moving out to the most general. This allows
+ * general property defaults to be set and then overiden for specific uses by some classes and modifiers.
+ *
+ * <p>A ContextualProperties object can be loaded in the same way as a java.utils.Properties. A recommended way to do
+ * this that does not assume that the properties file is a file (it could be in a jar) is to load the properties from the
+ * url for the resource lookup up on the classpath:
+ *
+ * <p><code>
+ * Properties configProperties = new ContextualProperties();<br/>
+ * configProperties.load(this.getClass().getClassLoader().getResourceAsStream("config.properties"));<br/>
+ * </code>
+ *
+ * <p>EnvironmentProperties will load the 'DEVELOPMENT.debug' property or 'PROUCTION.debug' property based on the setting
+ * of the system environment property. If a matching property for the environment cannot be found then the simple property
+ * name without the environment pre-pended onto it will be used instead. This 'use of default environments' behaviour is
+ * turned on initially but it can be disabled by calling the {@link #useDefaultEnvironments} method.
+ *
+ * <p>When a property matching a key cannot be found then the property accessor methods will always return null. If a
+ * default value for a property exists but the 'use of default environments' behavious prevents it being used then the
+ * accessor methods will return null.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Automatically select properties dependant on environment, class name and modifier as well as property key.
+ * <tr><td> Convert indexed properties into arrays.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ContextualProperties extends ParsedProperties
+{
+ /** The name of the system property that is used to define the environment. */
+ public static final String ENV_SYS_PROPERTY = "environment";
+
+ /**
+ * <p>Holds the iteration count down order.
+ *
+ * <p>If e = 4, b = 2, m = 1 then the iteration order or i is 7,6,4 and then if using environment defaults 3,2,0
+ * where the accessor key is:
+ * (i & e != 0 ? environment : "") + (i & b != 0 ? base : "") + (1 + m != 0 ? modifier : "") + key
+ *
+ * <p>In other words the presence or otherwise of the three least significant bits when counting down from 7
+ * specifies which of the environment, base and modifier are to be included in the key where the environment, base
+ * and modifier stand for the bits in positions 2, 1 and 0. The numbers 5 and 1 are missed out of the count because
+ * they stand for the case where the modifier is used without the base which is not done.
+ */
+ private static final int[] ORDER = new int[] { 7, 6, 4, 3, 2, 0 };
+
+ /**
+ * Defines the point in the iteration count order below which the 'use environment defaults' feature is being used.
+ */
+ private static final int ENVIRONMENT_DEFAULTS_CUTOFF = 4;
+
+ /** Defines the bit representation for the environment in the key ordering. See {@link #ORDER}. */
+ private static final int E = 4;
+
+ /** Defines the bit representation for the base in the key ordering. See {@link #ORDER}. */
+ private static final int B = 2;
+
+ /** Defines the bit representation for the modifier in the key ordering. See {@link #ORDER}. */
+ private static final int M = 1;
+
+ /** Used to hold the value of the environment system property. */
+ private String environment;
+
+ /** Used to indicate that the 'use of defaults' behaviour should be used. */
+ private boolean useDefaults = true;
+
+ /** Used to hold all the array properties. This is a mapping from property names to ArrayLists of Strings. */
+ protected Map arrayProperties = new HashMap();
+
+ /**
+ * Default constructor that builds a ContextualProperties that uses environment defaults.
+ */
+ public ContextualProperties()
+ {
+ super();
+
+ // Keep the value of the system environment property.
+ environment = System.getProperty(ENV_SYS_PROPERTY);
+ }
+
+ /**
+ * Creates a ContextualProperties that uses environment defaults and is initialized with the specified properties.
+ *
+ * @param props The properties to initialize this with.
+ */
+ public ContextualProperties(Properties props)
+ {
+ super(props);
+
+ // Keep the value of the system environment property.
+ environment = System.getProperty(ENV_SYS_PROPERTY);
+
+ // Extract any array properties as arrays.
+ createArrayProperties();
+ }
+
+ /**
+ * Parses an input stream as properties.
+ *
+ * @param inStream The input stream to read the properties from.
+ *
+ * @exception IOException If there is an IO error during reading from the input stream.
+ */
+ public void load(InputStream inStream) throws IOException
+ {
+ super.load(inStream);
+
+ // Extract any array properties as arrays.
+ createArrayProperties();
+ }
+
+ /**
+ * Tells this environment aware properties object whether it should use default environment properties without a
+ * pre-pended environment when a property for the current environment cannot be found.
+ *
+ * @param flag True to use defaults, false to not use defaults.
+ */
+ public void useDefaultEnvironments(boolean flag)
+ {
+ useDefaults = flag;
+ }
+
+ /**
+ * Looks up a property value relative to the environment, callers class and method. The default environment will be
+ * checked for a matching property if defaults are being used. In order to work out the callers class and method this
+ * method throws an exception and then searches one level up its stack frames.
+ *
+ * @param key The property key.
+ *
+ * @return The value of this property searching from the most specific definition (environment, class, method, key)
+ * to the most general (key only), unless use of default environments is turned off in which case the most general
+ * proeprty searched is (environment, key).
+ */
+ public String getProperty(String key)
+ {
+ // Try to get the callers class name and method name by examing the stack.
+ String className = null;
+ String methodName = null;
+
+ // Java 1.4 onwards only.
+ /*try
+ {
+ throw new Exception();
+ }
+ catch (Exception e)
+ {
+ StackTraceElement[] stack = e.getStackTrace();
+
+ // Check that the stack trace contains at least two elements, one for this method and one for the caller.
+ if (stack.length >= 2)
+ {
+ className = stack[1].getClassName();
+ methodName = stack[1].getMethodName();
+ }
+ }*/
+
+ // Java 1.5 onwards only.
+ StackTraceElement[] stack = Thread.currentThread().getStackTrace();
+
+ // Check that the stack trace contains at least two elements, one for this method and one for the caller.
+ if (stack.length >= 2)
+ {
+ className = stack[1].getClassName();
+ methodName = stack[1].getMethodName();
+ }
+
+ // Java 1.3 and before? Not sure, some horrible thing that parses the text spat out by printStackTrace?
+
+ return getProperty(className, methodName, key);
+ }
+
+ /**
+ * Looks up a property value relative to the environment, base class and modifier. The default environment will be
+ * checked for a matching property if defaults are being used.
+ *
+ * @param base An object of the class to retrieve properties relative to.
+ * @param modifier The modifier (which may stand for a method of the class).
+ * @param key The property key.
+ *
+ * @return The value of this property searching from the most specific definition (environment, class, modifier, key)
+ * to the most general (key only), unless use of default environments is turned off in which case the most general
+ * property searched is (environment, key).
+ */
+ public String getProperty(Object base, String modifier, String key)
+ {
+ return getProperty(base.getClass().getName(), modifier, key);
+ }
+
+ /**
+ * Looks up a property value relative to the environment, base class and modifier. The default environment will be
+ * checked for a matching property if defaults are being used.
+ *
+ * @param base The name of the class to retrieve properties relative to.
+ * @param modifier The modifier (which may stand for a method of the class).
+ * @param key The property key.
+ *
+ * @return The value of this property searching from the most specific definition (environment, class, modifier, key)
+ * to the most general (key only), unless use of default environments is turned off in which case the most general
+ * property searched is (environment, key).
+ */
+ public String getProperty(String base, String modifier, String key)
+ {
+ String result = null;
+
+ // Loop over the key orderings, from the most specific to the most general, until a matching value is found.
+ for (Iterator i = getKeyIterator(base, modifier, key); i.hasNext();)
+ {
+ String nextKey = (String) i.next();
+
+ result = super.getProperty(nextKey);
+
+ if (result != null)
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Looks up an array property value relative to the environment, callers class and method. The default environment
+ * will be checked for a matching array property if defaults are being used. In order to work out the callers class
+ * and method this method throws an exception and then searches one level up its stack frames.
+ *
+ * @param key The property key.
+ *
+ * @return The array value of this indexed property searching from the most specific definition (environment, class,
+ * method, key) to the most general (key only), unless use of default environments is turned off in which
+ * case the most general proeprty searched is (environment, key).
+ */
+ public String[] getProperties(String key)
+ {
+ // Try to get the callers class name and method name by throwing an exception an searching the stack frames.
+ String className = null;
+ String methodName = null;
+
+ /* Java 1.4 onwards only.
+ try {
+ throw new Exception();
+ } catch (Exception e) {
+ StackTraceElement[] stack = e.getStackTrace();
+ // Check that the stack trace contains at least two elements, one for this method and one for the caller.
+ if (stack.length >= 2) {
+ className = stack[1].getClassName();
+ methodName = stack[1].getMethodName();
+ }
+ }*/
+ return getProperties(className, methodName, key);
+ }
+
+ /**
+ * Looks up an array property value relative to the environment, base class and modifier. The default environment will
+ * be checked for a matching array property if defaults are being used.
+ *
+ * @param base An object of the class to retrieve properties relative to.
+ * @param modifier The modifier (which may stand for a method of the class).
+ * @param key The property key.
+ *
+ * @return The array value of this indexed property searching from the most specific definition (environment, class,
+ * modifier, key) to the most general (key only), unless use of default environments is turned off in which
+ * case the most general proeprty searched is (environment, key).
+ */
+ public String[] getProperties(Object base, String modifier, String key)
+ {
+ return getProperties(base.getClass().getName(), modifier, key);
+ }
+
+ /**
+ * Looks up an array property value relative to the environment, base class and modifier. The default environment will
+ * be checked for a matching array property if defaults are being used.
+ *
+ * @param base The name of the class to retrieve properties relative to.
+ * @param modifier The modifier (which may stand for a method of the class).
+ * @param key The property key.
+ *
+ * @return The array value of this indexed property searching from the most specific definition (environment, class,
+ * modifier, key) to the most general (key only), unless use of default environments is turned off in which
+ * case the most general property searched is (environment, key).
+ */
+ public String[] getProperties(String base, String modifier, String key)
+ {
+ String[] result = null;
+
+ // Loop over the key orderings, from the most specific to the most general, until a matching value is found.
+ for (Iterator i = getKeyIterator(base, modifier, key); i.hasNext();)
+ {
+ String nextKey = (String) i.next();
+ ArrayList arrayList = (ArrayList) arrayProperties.get(nextKey);
+
+ if (arrayList != null)
+ {
+ result = (String[]) arrayList.toArray(new String[] {});
+
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * For a given environment, base, modifier and key and setting of the use of default environments feature this
+ * generates an iterator that walks over the order in which to try and access properties.
+ *
+ * <p>See the {@link #ORDER} constant for an explanation of how the key ordering is generated.
+ *
+ * @param base The name of the class to retrieve properties relative to.
+ * @param modifier The modifier (which may stand for a method of the class).
+ * @param key The property key.
+ *
+ * @return An Iterator over String keys defining the order in which properties should be accessed.
+ */
+ protected Iterator getKeyIterator(final String base, final String modifier, final String key)
+ {
+ return new Iterator()
+ {
+ // The key ordering count always begins at the start of the ORDER array.
+ private int i = 0;
+
+ public boolean hasNext()
+ {
+ return (useDefaults ? ((i < ORDER.length) && (ORDER[i] > ENVIRONMENT_DEFAULTS_CUTOFF))
+ : (i < ORDER.length));
+ }
+
+ public Object next()
+ {
+ // Check that there is a next element and return null if not.
+ if (!hasNext())
+ {
+ return null;
+ }
+
+ // Get the next ordering count.
+ int o = ORDER[i];
+
+ // Do bit matching on the count to choose which elements to include in the key.
+ String result =
+ (((o & E) != 0) ? (environment + ".") : "") + (((o & B) != 0) ? (base + ".") : "")
+ + (((o & M) != 0) ? (modifier + ".") : "") + key;
+
+ // Increment the iterator to get the next key on the next call.
+ i++;
+
+ return result;
+ }
+
+ public void remove()
+ {
+ // This method is not supported.
+ throw new UnsupportedOperationException("remove() is not supported on this key order iterator as "
+ + "the ordering cannot be changed");
+ }
+ };
+ }
+
+ /**
+ * Scans all the properties in the parent Properties object and creates arrays for any array property definitions.
+ *
+ * <p>Array properties are defined with indexes. For example:
+ *
+ * <p><code>
+ * property.1=one<br/>
+ * property.2=two<br/>
+ * property.3=three<br/>
+ * </code>
+ *
+ * <p>Note that these properties will be stored as the 'empty string' or "" property array.
+ *
+ * <p><code>
+ * .1=one<br/>
+ * 2=two<br/>
+ * </code>
+ */
+ protected void createArrayProperties()
+ {
+ // Scan through all defined properties.
+ for (Object o : keySet())
+ {
+ String key = (String) o;
+ String value = super.getProperty(key);
+
+ // Split the property key into everything before the last '.' and after it.
+ int lastDotIndex = key.lastIndexOf('.');
+ String keyEnding = key.substring(lastDotIndex + 1, key.length());
+ String keyStart = key.substring(0, (lastDotIndex == -1) ? 0 : lastDotIndex);
+
+ // Check if the property key ends in an integer, in which case it is an array property.
+ int index = 0;
+
+ try
+ {
+ index = Integer.parseInt(keyEnding);
+ }
+ // The ending is not an integer so its not an array.
+ catch (NumberFormatException e)
+ {
+ // Scan the next property.
+ continue;
+ }
+
+ // Check if an array property already exists for this base name and create one if not.
+ ArrayList propArray = (ArrayList) arrayProperties.get(keyStart);
+
+ if (propArray == null)
+ {
+ propArray = new ArrayList();
+ arrayProperties.put(keyStart, propArray);
+ }
+
+ // Add the new property value to the array property for the index.
+ propArray.set(index, value);
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java
index 7a45632643..7c803294f4 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/MathUtils.java
@@ -1,428 +1,428 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Mathematical support methods for the toolkit. Caculating averages, variances, min/max for test latencies and
- * generating linear/exponential sequences for test size/concurrency ramping up.
- *
- * <p/>The sequence specifications are of the form [lowest(, ...)(, highest)](,sample=s)(,exp), where round brackets
- * enclose optional values. Using this pattern form it is possible to specify a single value, a range of values divided
- * into s samples, a range of values divided into s samples but distributed exponentially, or a fixed set of samples.
- *
- * <p/>The duration arguments are of the form (dD)(hH)(mM)(sS), where round brackets enclose optional values. At least
- * one of the optional values must be present.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Generate a sequene of integers from a sequence specification.
- * <tr><td> Parse an encoded duration into milliseconds.
- * </table>
- *
- * @author Rupert Smith
- */
-public class MathUtils
-{
- /** Used for debugging. */
- // private static final Logger log = Logger.getLogger(MathUtils.class);
-
- /** The sequence defintion matching regular expression. */
- public static final String SEQUENCE_REGEXP = "^(\\[[0-9:]+\\])(:samples=[0-9]+)?(:exp)?$";
-
- /** The regular expression that matches sequence definitions. */
- private static final Pattern SEQUENCE_PATTERN = Pattern.compile(SEQUENCE_REGEXP);
-
- /** The duration definition matching regular expression. */
- public static final String DURATION_REGEXP = "^(\\d+D)?(\\d+H)?(\\d+M)?(\\d+S)?$";
-
- /** The regular expression that matches the duration expression. */
- public static final Pattern DURATION_PATTERN = Pattern.compile(DURATION_REGEXP);
-
- /** For matching name=value pairs. */
- public static final String NAME_VALUE_REGEXP = "^\\w+=\\w+$";
-
- /** For matching name=[value1: value2: ...] variations. */
- public static final String NAME_VALUE_VARIATION_REGEXP = "^\\w+=\\[[\\w:]+\\]$";
-
- /** For matching name=[n: ... :m](:sample=s)(:exp) sequences. */
- public static final String NAME_VALUE_SEQUENCE_REGEXP = "^\\w+=(\\[[0-9:]+\\])(:samples=[0-9]+)?(:exp)?$";
-
- /** The regular expression that matches name=value pairs and variations. */
- public static final Pattern NAME_VALUE_PATTERN =
- Pattern.compile("(" + NAME_VALUE_REGEXP + ")|(" + NAME_VALUE_VARIATION_REGEXP + ")|(" + NAME_VALUE_SEQUENCE_REGEXP
- + ")");
-
- /**
- * Runs a quick test of the sequence generation methods to confirm that they work as expected.
- *
- * @param args The command line parameters.
- */
- public static void main(String[] args)
- {
- // Use the command line parser to evaluate the command line.
- CommandLineParser commandLine =
- new CommandLineParser(
- new String[][]
- {
- { "s", "The sequence definition.", "[m:...:n](:sample=s)(:exp)", "true", MathUtils.SEQUENCE_REGEXP },
- { "d", "The duration definition.", "dDhHmMsS", "false", MathUtils.DURATION_REGEXP }
- });
-
- // Capture the command line arguments or display errors and correct usage and then exit.
- ParsedProperties options = null;
-
- try
- {
- options = new ParsedProperties(commandLine.parseCommandLine(args));
- }
- catch (IllegalArgumentException e)
- {
- System.out.println(commandLine.getErrors());
- System.out.println(commandLine.getUsage());
- System.exit(-1);
- }
-
- // Extract the command line options.
- String sequence = options.getProperty("s");
- String durationString = options.getProperty("d");
-
- System.out.println("Sequence is: " + printArray(parseSequence(sequence)));
-
- if (durationString != null)
- {
- System.out.println("Duration is: " + parseDuration(durationString));
- }
- }
-
- /**
- * Given a start and end and a number of steps this method generates a sequence of evenly spaced integer
- * values, starting at the start (inclusive) and finishing at the end (inclusive) with the specified number
- * of values in the sequence. The sequence returned may contain less than the specified number where the integer
- * range between start and end is too small to contain that many.
- *
- * <p/>As the results are integers, they will not be perfectly evenly spaced but a best-fit.
- *
- * @param start The sequence start.
- * @param end The sequence end.
- * @param steps The number of steps.
- *
- * @return The sequence.
- */
- public static int[] generateSequence(int start, int end, int steps)
- {
- // Check that there are at least two steps.
- if (steps < 2)
- {
- throw new IllegalArgumentException("There must be at least 2 steps.");
- }
-
- ArrayList<Integer> result = new ArrayList<Integer>();
-
- // Calculate the sequence using floating point, then round into the results.
- double fStart = start;
- double fEnd = end;
- double fCurrent = start;
-
- for (int i = 0; i < steps; i++)
- {
- fCurrent = (((fEnd - fStart) / (steps - 1)) * i) + fStart;
-
- roundAndAdd(result, fCurrent);
- }
-
- // Return the results after converting to a primitive array.
- return intListToPrimitiveArray(result);
- }
-
- /**
- * Given a start and end and a number of steps this method generates a sequence of expontentially spaced integer
- * values, starting at the start (inclusive) and finishing at the end (inclusive) with the specified number
- * of values in the sequence. An exponentially spaced sequence is one where the ratio between any two consecutive
- * numbers in the sequence remains constant. The sequence returned may contain less than the specified number where
- * the difference between two consecutive values is too small (this is more likely at the start of the sequence,
- * where the values are closer together).
- *
- * <p/>As the results are integers, they will not be perfectly exponentially spaced but a best-fit.
- *
- * @param start The sequence start.
- * @param end The sequence end.
- * @param steps The number of steps.
- *
- * @return The sequence.
- */
- public static int[] generateExpSequence(int start, int end, int steps)
- {
- // Check that there are at least two steps.
- if (steps < 2)
- {
- throw new IllegalArgumentException("There must be at least 2 steps.");
- }
-
- ArrayList<Integer> result = new ArrayList<Integer>();
-
- // Calculate the sequence using floating point, then round into the results.
- double fStart = start;
- double fEnd = end;
- // float fCurrent = start;
- double diff = fEnd - fStart;
- double factor = java.lang.Math.pow(diff, (1.0f / (steps - 1)));
-
- for (int i = 0; i < steps; i++)
- {
- // This is a cheat to get the end exactly on and lose the accumulated rounding error.
- if (i == (steps - 1))
- {
- result.add(end);
- }
- else
- {
- roundAndAdd(result, fStart - 1.0f + java.lang.Math.pow(factor, i));
- }
- }
-
- // Return the results after converting to a primitive array.
- return intListToPrimitiveArray(result);
- }
-
- /**
- * Parses a string defintion of a sequence into an int array containing the sequence. The definition will conform
- * to the regular expression: "^(\[[0-9,]+\])(,samples=[0-9]+)?(,exp)?$". This splits it into three parts,
- * an array of integers, the optional sample count and the optional exponential flag.
- *
- * @param sequenceDef The sequence definition.
- *
- * @return The sequence as a fully expanded int array.
- */
- public static int[] parseSequence(String sequenceDef)
- {
- // Match the sequence definition against the regular expression for sequences.
- Matcher matcher = SEQUENCE_PATTERN.matcher(sequenceDef);
-
- // Check that the argument is of the right format accepted by this method.
- if (!matcher.matches())
- {
- throw new IllegalArgumentException("The sequence definition is not in the correct format.");
- }
-
- // Get the total number of matching groups to see if either of the optional samples or exponential flag
- // goups were set.
- int numGroups = matcher.groupCount();
-
- // Split the array of integers on commas.
- String intArrayString = matcher.group(1);
-
- String[] intSplits = intArrayString.split("[:\\[\\]]");
-
- int[] sequence = new int[intSplits.length - 1];
-
- for (int i = 1; i < intSplits.length; i++)
- {
- sequence[i - 1] = Integer.parseInt(intSplits[i]);
- }
-
- // Check for the optional samples count.
- int samples = 0;
-
- if ((numGroups > 1) && (matcher.group(2) != null))
- {
- String samplesGroup = matcher.group(2);
-
- String samplesString = samplesGroup.substring(",samples=".length());
- samples = Integer.parseInt(samplesString);
- }
-
- // Check for the optional exponential flag.
- boolean expFlag = false;
-
- if ((numGroups > 2) && (matcher.group(3) != null))
- {
- expFlag = true;
- }
-
- // If there is a sample count and 2 or more sequence values defined, then generate the sequence from the first
- // and last sequence values.
- if ((samples != 0) && (sequence.length >= 2))
- {
- int start = sequence[0];
- int end = sequence[sequence.length - 1];
-
- if (!expFlag)
- {
- sequence = generateSequence(start, end, samples);
- }
- else
- {
- sequence = generateExpSequence(start, end, samples);
- }
- }
-
- return sequence;
- }
-
- /**
- * Parses a duration defined as a string, giving a duration in days, hours, minutes and seconds into a number
- * of milliseconds equal to that duration.
- *
- * @param duration The duration definition string.
- *
- * @return The duration in millliseconds.
- */
- public static long parseDuration(String duration)
- {
- // Match the duration against the regular expression.
- Matcher matcher = DURATION_PATTERN.matcher(duration);
-
- // Check that the argument is of the right format accepted by this method.
- if (!matcher.matches())
- {
- throw new IllegalArgumentException("The duration definition is not in the correct format.");
- }
-
- // This accumulates the duration.
- long result = 0;
-
- int numGroups = matcher.groupCount();
-
- // Extract the days.
- if (numGroups >= 1)
- {
- String daysString = matcher.group(1);
- result +=
- (daysString == null)
- ? 0 : (Long.parseLong(daysString.substring(0, daysString.length() - 1)) * 24 * 60 * 60 * 1000);
- }
-
- // Extract the hours.
- if (numGroups >= 2)
- {
- String hoursString = matcher.group(2);
- result +=
- (hoursString == null) ? 0
- : (Long.parseLong(hoursString.substring(0, hoursString.length() - 1)) * 60 * 60 * 1000);
- }
-
- // Extract the minutes.
- if (numGroups >= 3)
- {
- String minutesString = matcher.group(3);
- result +=
- (minutesString == null)
- ? 0 : (Long.parseLong(minutesString.substring(0, minutesString.length() - 1)) * 60 * 1000);
- }
-
- // Extract the seconds.
- if (numGroups >= 4)
- {
- String secondsString = matcher.group(4);
- result +=
- (secondsString == null) ? 0 : (Long.parseLong(secondsString.substring(0, secondsString.length() - 1)) * 1000);
- }
-
- return result;
- }
-
- /**
- * Pretty prints an array of ints as a string.
- *
- * @param array The array to pretty print.
- *
- * @return The pretty printed string.
- */
- public static String printArray(int[] array)
- {
- String result = "[";
- for (int i = 0; i < array.length; i++)
- {
- result += array[i];
- result += (i < (array.length - 1)) ? ", " : "";
- }
-
- result += "]";
-
- return result;
- }
-
- /**
- * Returns the maximum value in an array of integers.
- *
- * @param values The array to find the amx in.
- *
- * @return The max value.
- */
- public static int maxInArray(int[] values)
- {
- if ((values == null) || (values.length == 0))
- {
- throw new IllegalArgumentException("Cannot find the max of a null or empty array.");
- }
-
- int max = values[0];
-
- for (int value : values)
- {
- max = (max < value) ? value : max;
- }
-
- return max;
- }
-
- /**
- * The #toArray methods of collections cannot be used with primitive arrays. This loops over and array list
- * of Integers and outputs and array of int.
- *
- * @param result The array of Integers to convert.
- *
- * @return An array of int.
- */
- private static int[] intListToPrimitiveArray(ArrayList<Integer> result)
- {
- int[] resultArray = new int[result.size()];
- int index = 0;
- for (int r : result)
- {
- resultArray[index] = result.get(index);
- index++;
- }
-
- return resultArray;
- }
-
- /**
- * Rounds the specified floating point value to the nearest integer and adds it to the specified list of
- * integers, provided it is not already in the list.
- *
- * @param result The list of integers to add to.
- * @param value The new candidate to round and add to the list.
- */
- private static void roundAndAdd(ArrayList<Integer> result, double value)
- {
- int roundedValue = (int) Math.round(value);
-
- if (!result.contains(roundedValue))
- {
- result.add(roundedValue);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Mathematical support methods for the toolkit. Caculating averages, variances, min/max for test latencies and
+ * generating linear/exponential sequences for test size/concurrency ramping up.
+ *
+ * <p/>The sequence specifications are of the form [lowest(, ...)(, highest)](,sample=s)(,exp), where round brackets
+ * enclose optional values. Using this pattern form it is possible to specify a single value, a range of values divided
+ * into s samples, a range of values divided into s samples but distributed exponentially, or a fixed set of samples.
+ *
+ * <p/>The duration arguments are of the form (dD)(hH)(mM)(sS), where round brackets enclose optional values. At least
+ * one of the optional values must be present.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Generate a sequene of integers from a sequence specification.
+ * <tr><td> Parse an encoded duration into milliseconds.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class MathUtils
+{
+ /** Used for debugging. */
+ // private static final Logger log = Logger.getLogger(MathUtils.class);
+
+ /** The sequence defintion matching regular expression. */
+ public static final String SEQUENCE_REGEXP = "^(\\[[0-9:]+\\])(:samples=[0-9]+)?(:exp)?$";
+
+ /** The regular expression that matches sequence definitions. */
+ private static final Pattern SEQUENCE_PATTERN = Pattern.compile(SEQUENCE_REGEXP);
+
+ /** The duration definition matching regular expression. */
+ public static final String DURATION_REGEXP = "^(\\d+D)?(\\d+H)?(\\d+M)?(\\d+S)?$";
+
+ /** The regular expression that matches the duration expression. */
+ public static final Pattern DURATION_PATTERN = Pattern.compile(DURATION_REGEXP);
+
+ /** For matching name=value pairs. */
+ public static final String NAME_VALUE_REGEXP = "^\\w+=\\w+$";
+
+ /** For matching name=[value1: value2: ...] variations. */
+ public static final String NAME_VALUE_VARIATION_REGEXP = "^\\w+=\\[[\\w:]+\\]$";
+
+ /** For matching name=[n: ... :m](:sample=s)(:exp) sequences. */
+ public static final String NAME_VALUE_SEQUENCE_REGEXP = "^\\w+=(\\[[0-9:]+\\])(:samples=[0-9]+)?(:exp)?$";
+
+ /** The regular expression that matches name=value pairs and variations. */
+ public static final Pattern NAME_VALUE_PATTERN =
+ Pattern.compile("(" + NAME_VALUE_REGEXP + ")|(" + NAME_VALUE_VARIATION_REGEXP + ")|(" + NAME_VALUE_SEQUENCE_REGEXP
+ + ")");
+
+ /**
+ * Runs a quick test of the sequence generation methods to confirm that they work as expected.
+ *
+ * @param args The command line parameters.
+ */
+ public static void main(String[] args)
+ {
+ // Use the command line parser to evaluate the command line.
+ CommandLineParser commandLine =
+ new CommandLineParser(
+ new String[][]
+ {
+ { "s", "The sequence definition.", "[m:...:n](:sample=s)(:exp)", "true", MathUtils.SEQUENCE_REGEXP },
+ { "d", "The duration definition.", "dDhHmMsS", "false", MathUtils.DURATION_REGEXP }
+ });
+
+ // Capture the command line arguments or display errors and correct usage and then exit.
+ ParsedProperties options = null;
+
+ try
+ {
+ options = new ParsedProperties(commandLine.parseCommandLine(args));
+ }
+ catch (IllegalArgumentException e)
+ {
+ System.out.println(commandLine.getErrors());
+ System.out.println(commandLine.getUsage());
+ System.exit(-1);
+ }
+
+ // Extract the command line options.
+ String sequence = options.getProperty("s");
+ String durationString = options.getProperty("d");
+
+ System.out.println("Sequence is: " + printArray(parseSequence(sequence)));
+
+ if (durationString != null)
+ {
+ System.out.println("Duration is: " + parseDuration(durationString));
+ }
+ }
+
+ /**
+ * Given a start and end and a number of steps this method generates a sequence of evenly spaced integer
+ * values, starting at the start (inclusive) and finishing at the end (inclusive) with the specified number
+ * of values in the sequence. The sequence returned may contain less than the specified number where the integer
+ * range between start and end is too small to contain that many.
+ *
+ * <p/>As the results are integers, they will not be perfectly evenly spaced but a best-fit.
+ *
+ * @param start The sequence start.
+ * @param end The sequence end.
+ * @param steps The number of steps.
+ *
+ * @return The sequence.
+ */
+ public static int[] generateSequence(int start, int end, int steps)
+ {
+ // Check that there are at least two steps.
+ if (steps < 2)
+ {
+ throw new IllegalArgumentException("There must be at least 2 steps.");
+ }
+
+ ArrayList<Integer> result = new ArrayList<Integer>();
+
+ // Calculate the sequence using floating point, then round into the results.
+ double fStart = start;
+ double fEnd = end;
+ double fCurrent = start;
+
+ for (int i = 0; i < steps; i++)
+ {
+ fCurrent = (((fEnd - fStart) / (steps - 1)) * i) + fStart;
+
+ roundAndAdd(result, fCurrent);
+ }
+
+ // Return the results after converting to a primitive array.
+ return intListToPrimitiveArray(result);
+ }
+
+ /**
+ * Given a start and end and a number of steps this method generates a sequence of expontentially spaced integer
+ * values, starting at the start (inclusive) and finishing at the end (inclusive) with the specified number
+ * of values in the sequence. An exponentially spaced sequence is one where the ratio between any two consecutive
+ * numbers in the sequence remains constant. The sequence returned may contain less than the specified number where
+ * the difference between two consecutive values is too small (this is more likely at the start of the sequence,
+ * where the values are closer together).
+ *
+ * <p/>As the results are integers, they will not be perfectly exponentially spaced but a best-fit.
+ *
+ * @param start The sequence start.
+ * @param end The sequence end.
+ * @param steps The number of steps.
+ *
+ * @return The sequence.
+ */
+ public static int[] generateExpSequence(int start, int end, int steps)
+ {
+ // Check that there are at least two steps.
+ if (steps < 2)
+ {
+ throw new IllegalArgumentException("There must be at least 2 steps.");
+ }
+
+ ArrayList<Integer> result = new ArrayList<Integer>();
+
+ // Calculate the sequence using floating point, then round into the results.
+ double fStart = start;
+ double fEnd = end;
+ // float fCurrent = start;
+ double diff = fEnd - fStart;
+ double factor = java.lang.Math.pow(diff, (1.0f / (steps - 1)));
+
+ for (int i = 0; i < steps; i++)
+ {
+ // This is a cheat to get the end exactly on and lose the accumulated rounding error.
+ if (i == (steps - 1))
+ {
+ result.add(end);
+ }
+ else
+ {
+ roundAndAdd(result, fStart - 1.0f + java.lang.Math.pow(factor, i));
+ }
+ }
+
+ // Return the results after converting to a primitive array.
+ return intListToPrimitiveArray(result);
+ }
+
+ /**
+ * Parses a string defintion of a sequence into an int array containing the sequence. The definition will conform
+ * to the regular expression: "^(\[[0-9,]+\])(,samples=[0-9]+)?(,exp)?$". This splits it into three parts,
+ * an array of integers, the optional sample count and the optional exponential flag.
+ *
+ * @param sequenceDef The sequence definition.
+ *
+ * @return The sequence as a fully expanded int array.
+ */
+ public static int[] parseSequence(String sequenceDef)
+ {
+ // Match the sequence definition against the regular expression for sequences.
+ Matcher matcher = SEQUENCE_PATTERN.matcher(sequenceDef);
+
+ // Check that the argument is of the right format accepted by this method.
+ if (!matcher.matches())
+ {
+ throw new IllegalArgumentException("The sequence definition is not in the correct format.");
+ }
+
+ // Get the total number of matching groups to see if either of the optional samples or exponential flag
+ // goups were set.
+ int numGroups = matcher.groupCount();
+
+ // Split the array of integers on commas.
+ String intArrayString = matcher.group(1);
+
+ String[] intSplits = intArrayString.split("[:\\[\\]]");
+
+ int[] sequence = new int[intSplits.length - 1];
+
+ for (int i = 1; i < intSplits.length; i++)
+ {
+ sequence[i - 1] = Integer.parseInt(intSplits[i]);
+ }
+
+ // Check for the optional samples count.
+ int samples = 0;
+
+ if ((numGroups > 1) && (matcher.group(2) != null))
+ {
+ String samplesGroup = matcher.group(2);
+
+ String samplesString = samplesGroup.substring(",samples=".length());
+ samples = Integer.parseInt(samplesString);
+ }
+
+ // Check for the optional exponential flag.
+ boolean expFlag = false;
+
+ if ((numGroups > 2) && (matcher.group(3) != null))
+ {
+ expFlag = true;
+ }
+
+ // If there is a sample count and 2 or more sequence values defined, then generate the sequence from the first
+ // and last sequence values.
+ if ((samples != 0) && (sequence.length >= 2))
+ {
+ int start = sequence[0];
+ int end = sequence[sequence.length - 1];
+
+ if (!expFlag)
+ {
+ sequence = generateSequence(start, end, samples);
+ }
+ else
+ {
+ sequence = generateExpSequence(start, end, samples);
+ }
+ }
+
+ return sequence;
+ }
+
+ /**
+ * Parses a duration defined as a string, giving a duration in days, hours, minutes and seconds into a number
+ * of milliseconds equal to that duration.
+ *
+ * @param duration The duration definition string.
+ *
+ * @return The duration in millliseconds.
+ */
+ public static long parseDuration(String duration)
+ {
+ // Match the duration against the regular expression.
+ Matcher matcher = DURATION_PATTERN.matcher(duration);
+
+ // Check that the argument is of the right format accepted by this method.
+ if (!matcher.matches())
+ {
+ throw new IllegalArgumentException("The duration definition is not in the correct format.");
+ }
+
+ // This accumulates the duration.
+ long result = 0;
+
+ int numGroups = matcher.groupCount();
+
+ // Extract the days.
+ if (numGroups >= 1)
+ {
+ String daysString = matcher.group(1);
+ result +=
+ (daysString == null)
+ ? 0 : (Long.parseLong(daysString.substring(0, daysString.length() - 1)) * 24 * 60 * 60 * 1000);
+ }
+
+ // Extract the hours.
+ if (numGroups >= 2)
+ {
+ String hoursString = matcher.group(2);
+ result +=
+ (hoursString == null) ? 0
+ : (Long.parseLong(hoursString.substring(0, hoursString.length() - 1)) * 60 * 60 * 1000);
+ }
+
+ // Extract the minutes.
+ if (numGroups >= 3)
+ {
+ String minutesString = matcher.group(3);
+ result +=
+ (minutesString == null)
+ ? 0 : (Long.parseLong(minutesString.substring(0, minutesString.length() - 1)) * 60 * 1000);
+ }
+
+ // Extract the seconds.
+ if (numGroups >= 4)
+ {
+ String secondsString = matcher.group(4);
+ result +=
+ (secondsString == null) ? 0 : (Long.parseLong(secondsString.substring(0, secondsString.length() - 1)) * 1000);
+ }
+
+ return result;
+ }
+
+ /**
+ * Pretty prints an array of ints as a string.
+ *
+ * @param array The array to pretty print.
+ *
+ * @return The pretty printed string.
+ */
+ public static String printArray(int[] array)
+ {
+ String result = "[";
+ for (int i = 0; i < array.length; i++)
+ {
+ result += array[i];
+ result += (i < (array.length - 1)) ? ", " : "";
+ }
+
+ result += "]";
+
+ return result;
+ }
+
+ /**
+ * Returns the maximum value in an array of integers.
+ *
+ * @param values The array to find the amx in.
+ *
+ * @return The max value.
+ */
+ public static int maxInArray(int[] values)
+ {
+ if ((values == null) || (values.length == 0))
+ {
+ throw new IllegalArgumentException("Cannot find the max of a null or empty array.");
+ }
+
+ int max = values[0];
+
+ for (int value : values)
+ {
+ max = (max < value) ? value : max;
+ }
+
+ return max;
+ }
+
+ /**
+ * The #toArray methods of collections cannot be used with primitive arrays. This loops over and array list
+ * of Integers and outputs and array of int.
+ *
+ * @param result The array of Integers to convert.
+ *
+ * @return An array of int.
+ */
+ private static int[] intListToPrimitiveArray(ArrayList<Integer> result)
+ {
+ int[] resultArray = new int[result.size()];
+ int index = 0;
+ for (int r : result)
+ {
+ resultArray[index] = result.get(index);
+ index++;
+ }
+
+ return resultArray;
+ }
+
+ /**
+ * Rounds the specified floating point value to the nearest integer and adds it to the specified list of
+ * integers, provided it is not already in the list.
+ *
+ * @param result The list of integers to add to.
+ * @param value The new candidate to round and add to the list.
+ */
+ private static void roundAndAdd(ArrayList<Integer> result, double value)
+ {
+ int roundedValue = (int) Math.round(value);
+
+ if (!result.contains(roundedValue))
+ {
+ result.add(roundedValue);
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java
index 59c8cfbd3a..1cc6757675 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/ParsedProperties.java
@@ -1,390 +1,390 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.util.Properties;
-
-/**
- * ParsedProperties extends the basic Properties class with methods to extract properties, not as strings but as strings
- * parsed into basic types.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- *
- * @author Rupert Smith
- */
-public class ParsedProperties extends Properties
-{
- /**
- * Creates an empty ParsedProperties.
- */
- public ParsedProperties()
- {
- super();
- }
-
- /**
- * Creates a ParsedProperties initialized with the specified properties.
- *
- * @param props The properties to initialize this with.
- */
- public ParsedProperties(Properties props)
- {
- super(props);
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static boolean setSysPropertyIfNull(String propname, boolean value)
- {
- return Boolean.parseBoolean(setSysPropertyIfNull(propname, Boolean.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static short setSysPropertyIfNull(String propname, short value)
- {
- return Short.parseShort(setSysPropertyIfNull(propname, Short.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static int setSysPropertyIfNull(String propname, int value)
- {
- return Integer.parseInt(setSysPropertyIfNull(propname, Integer.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static long setSysPropertyIfNull(String propname, long value)
- {
- return Long.parseLong(setSysPropertyIfNull(propname, Long.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static float setSysPropertyIfNull(String propname, float value)
- {
- return Float.parseFloat(setSysPropertyIfNull(propname, Float.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public static double setSysPropertyIfNull(String propname, double value)
- {
- return Double.parseDouble(setSysPropertyIfNull(propname, Double.toString(value)));
- }
-
- /**
- * Helper method for setting system properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the system property after this method call.
- */
- public static String setSysPropertyIfNull(String propname, String value)
- {
- String property = System.getProperty(propname);
-
- if (property == null)
- {
- System.setProperty(propname, value);
-
- return value;
- }
- else
- {
- return property;
- }
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public boolean setPropertyIfNull(String propname, boolean value)
- {
- return Boolean.parseBoolean(setPropertyIfNull(propname, Boolean.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public short setPropertyIfNull(String propname, short value)
- {
- return Short.parseShort(setPropertyIfNull(propname, Short.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public int setPropertyIfNull(String propname, int value)
- {
- return Integer.parseInt(setPropertyIfNull(propname, Integer.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public long setPropertyIfNull(String propname, long value)
- {
- return Long.parseLong(setPropertyIfNull(propname, Long.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public float setPropertyIfNull(String propname, float value)
- {
- return Float.parseFloat(setPropertyIfNull(propname, Float.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public double setPropertyIfNull(String propname, double value)
- {
- return Double.parseDouble(setPropertyIfNull(propname, Double.toString(value)));
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public String setPropertyIfNull(String propname, String value)
- {
- String property = super.getProperty(propname);
-
- if (property == null)
- {
- super.setProperty(propname, value);
-
- return value;
- }
- else
- {
- return property;
- }
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public boolean setProperty(String propname, boolean value)
- {
- setProperty(propname, Boolean.toString(value));
-
- return value;
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public short setProperty(String propname, short value)
- {
- setProperty(propname, Short.toString(value));
-
- return value;
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public int setProperty(String propname, int value)
- {
- setProperty(propname, Integer.toString(value));
-
- return value;
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public long setProperty(String propname, long value)
- {
- setProperty(propname, Long.toString(value));
-
- return value;
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public float setProperty(String propname, float value)
- {
- setProperty(propname, Float.toString(value));
-
- return value;
- }
-
- /**
- * Helper method for setting properties.
- *
- * @param propname The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property after this method call.
- */
- public double setProperty(String propname, double value)
- {
- setProperty(propname, Double.toString(value));
-
- return value;
- }
-
- /**
- * Parses a property as a boolean.
- *
- * @param propName The property.
- *
- * @return The property as a boolean, or false if it does not exist.
- */
- public boolean getPropertyAsBoolean(String propName)
- {
- String prop = getProperty(propName);
-
- return (prop != null) && Boolean.parseBoolean(prop);
- }
-
- /**
- * Parses a property as an integer.
- *
- * @param propName The property.
- *
- * @return The property as a integer, or null if it does not exist.
- */
- public Integer getPropertyAsInteger(String propName)
- {
- String prop = getProperty(propName);
-
- return (prop != null) ? new Integer(prop) : null;
- }
-
- /**
- * Parses a property as a long.
- *
- * @param propName The property.
- *
- * @return The property as a long, or null if it does not exist.
- */
- public Long getPropertyAsLong(String propName)
- {
- String prop = getProperty(propName);
-
- return (prop != null) ? new Long(prop) : null;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.util.Properties;
+
+/**
+ * ParsedProperties extends the basic Properties class with methods to extract properties, not as strings but as strings
+ * parsed into basic types.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class ParsedProperties extends Properties
+{
+ /**
+ * Creates an empty ParsedProperties.
+ */
+ public ParsedProperties()
+ {
+ super();
+ }
+
+ /**
+ * Creates a ParsedProperties initialized with the specified properties.
+ *
+ * @param props The properties to initialize this with.
+ */
+ public ParsedProperties(Properties props)
+ {
+ super(props);
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static boolean setSysPropertyIfNull(String propname, boolean value)
+ {
+ return Boolean.parseBoolean(setSysPropertyIfNull(propname, Boolean.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static short setSysPropertyIfNull(String propname, short value)
+ {
+ return Short.parseShort(setSysPropertyIfNull(propname, Short.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static int setSysPropertyIfNull(String propname, int value)
+ {
+ return Integer.parseInt(setSysPropertyIfNull(propname, Integer.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static long setSysPropertyIfNull(String propname, long value)
+ {
+ return Long.parseLong(setSysPropertyIfNull(propname, Long.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static float setSysPropertyIfNull(String propname, float value)
+ {
+ return Float.parseFloat(setSysPropertyIfNull(propname, Float.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public static double setSysPropertyIfNull(String propname, double value)
+ {
+ return Double.parseDouble(setSysPropertyIfNull(propname, Double.toString(value)));
+ }
+
+ /**
+ * Helper method for setting system properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the system property after this method call.
+ */
+ public static String setSysPropertyIfNull(String propname, String value)
+ {
+ String property = System.getProperty(propname);
+
+ if (property == null)
+ {
+ System.setProperty(propname, value);
+
+ return value;
+ }
+ else
+ {
+ return property;
+ }
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public boolean setPropertyIfNull(String propname, boolean value)
+ {
+ return Boolean.parseBoolean(setPropertyIfNull(propname, Boolean.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public short setPropertyIfNull(String propname, short value)
+ {
+ return Short.parseShort(setPropertyIfNull(propname, Short.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public int setPropertyIfNull(String propname, int value)
+ {
+ return Integer.parseInt(setPropertyIfNull(propname, Integer.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public long setPropertyIfNull(String propname, long value)
+ {
+ return Long.parseLong(setPropertyIfNull(propname, Long.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public float setPropertyIfNull(String propname, float value)
+ {
+ return Float.parseFloat(setPropertyIfNull(propname, Float.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public double setPropertyIfNull(String propname, double value)
+ {
+ return Double.parseDouble(setPropertyIfNull(propname, Double.toString(value)));
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public String setPropertyIfNull(String propname, String value)
+ {
+ String property = super.getProperty(propname);
+
+ if (property == null)
+ {
+ super.setProperty(propname, value);
+
+ return value;
+ }
+ else
+ {
+ return property;
+ }
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public boolean setProperty(String propname, boolean value)
+ {
+ setProperty(propname, Boolean.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public short setProperty(String propname, short value)
+ {
+ setProperty(propname, Short.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public int setProperty(String propname, int value)
+ {
+ setProperty(propname, Integer.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public long setProperty(String propname, long value)
+ {
+ setProperty(propname, Long.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public float setProperty(String propname, float value)
+ {
+ setProperty(propname, Float.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Helper method for setting properties.
+ *
+ * @param propname The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property after this method call.
+ */
+ public double setProperty(String propname, double value)
+ {
+ setProperty(propname, Double.toString(value));
+
+ return value;
+ }
+
+ /**
+ * Parses a property as a boolean.
+ *
+ * @param propName The property.
+ *
+ * @return The property as a boolean, or false if it does not exist.
+ */
+ public boolean getPropertyAsBoolean(String propName)
+ {
+ String prop = getProperty(propName);
+
+ return (prop != null) && Boolean.parseBoolean(prop);
+ }
+
+ /**
+ * Parses a property as an integer.
+ *
+ * @param propName The property.
+ *
+ * @return The property as a integer, or null if it does not exist.
+ */
+ public Integer getPropertyAsInteger(String propName)
+ {
+ String prop = getProperty(propName);
+
+ return (prop != null) ? new Integer(prop) : null;
+ }
+
+ /**
+ * Parses a property as a long.
+ *
+ * @param propName The property.
+ *
+ * @return The property as a long, or null if it does not exist.
+ */
+ public Long getPropertyAsLong(String propName)
+ {
+ String prop = getProperty(propName);
+
+ return (prop != null) ? new Long(prop) : null;
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java
index 5f3ebb4545..ecc08770a9 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/SizeOf.java
@@ -1,94 +1,94 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-/**
- * SizeOf provides a static method that does its best to return an accurate measure of the total amount of memory used by
- * the virtual machine. This is calculated as the total memory available to the VM minus the actual amount used by it.
- * Before this measurement is taken the garbage collector is run many times until the used memory calculation stabilizes.
- * Generally, this trick works quite well to provide an accurate reading, however, it cannot be relied upon to be totally
- * accurate. It is also quite slow.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Calculate total memory used.
- * </table>
- *
- * @author Rupert Smith
- */
-public class SizeOf
-{
- /** Holds a reference to the runtime object. */
- private static final Runtime RUNTIME = Runtime.getRuntime();
-
- /**
- * Makes 4 calls the {@link #runGCTillStable} method.
- */
- public static void runGCTillStableSeveralTimes()
- {
- // It helps to call Runtime.gc() using several method calls.
- for (int r = 0; r < 4; ++r)
- {
- runGCTillStable();
- }
- }
-
- /**
- * Runs the garbage collector until the used memory reading stabilizes. It may run the garbage collector up
- * to 500 times.
- */
- public static void runGCTillStable()
- {
- long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
-
- for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i)
- {
- RUNTIME.runFinalization();
- RUNTIME.gc();
- Thread.currentThread().yield();
-
- usedMem2 = usedMem1;
- usedMem1 = usedMemory();
- }
- }
-
- /**
- * Runs the garbage collector until the used memory stabilizes and then measures it.
- *
- * @return The amount of memory used by the virtual machine.
- */
- public static long getUsedMemory()
- {
- runGCTillStableSeveralTimes();
-
- return usedMemory();
- }
-
- /**
- * Returns the amount of memory used by subtracting the free memory from the total available memory.
- *
- * @return The amount of memory used.
- */
- private static long usedMemory()
- {
- return RUNTIME.totalMemory() - RUNTIME.freeMemory();
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+/**
+ * SizeOf provides a static method that does its best to return an accurate measure of the total amount of memory used by
+ * the virtual machine. This is calculated as the total memory available to the VM minus the actual amount used by it.
+ * Before this measurement is taken the garbage collector is run many times until the used memory calculation stabilizes.
+ * Generally, this trick works quite well to provide an accurate reading, however, it cannot be relied upon to be totally
+ * accurate. It is also quite slow.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Calculate total memory used.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class SizeOf
+{
+ /** Holds a reference to the runtime object. */
+ private static final Runtime RUNTIME = Runtime.getRuntime();
+
+ /**
+ * Makes 4 calls the {@link #runGCTillStable} method.
+ */
+ public static void runGCTillStableSeveralTimes()
+ {
+ // It helps to call Runtime.gc() using several method calls.
+ for (int r = 0; r < 4; ++r)
+ {
+ runGCTillStable();
+ }
+ }
+
+ /**
+ * Runs the garbage collector until the used memory reading stabilizes. It may run the garbage collector up
+ * to 500 times.
+ */
+ public static void runGCTillStable()
+ {
+ long usedMem1 = usedMemory(), usedMem2 = Long.MAX_VALUE;
+
+ for (int i = 0; (usedMem1 < usedMem2) && (i < 500); ++i)
+ {
+ RUNTIME.runFinalization();
+ RUNTIME.gc();
+ Thread.currentThread().yield();
+
+ usedMem2 = usedMem1;
+ usedMem1 = usedMemory();
+ }
+ }
+
+ /**
+ * Runs the garbage collector until the used memory stabilizes and then measures it.
+ *
+ * @return The amount of memory used by the virtual machine.
+ */
+ public static long getUsedMemory()
+ {
+ runGCTillStableSeveralTimes();
+
+ return usedMemory();
+ }
+
+ /**
+ * Returns the amount of memory used by subtracting the free memory from the total available memory.
+ *
+ * @return The amount of memory used.
+ */
+ private static long usedMemory()
+ {
+ return RUNTIME.totalMemory() - RUNTIME.freeMemory();
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java
index 9078c0e247..acc1e2c218 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/StackQueue.java
@@ -1,131 +1,131 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.util.EmptyStackException;
-import java.util.NoSuchElementException;
-import java.util.Queue;
-import java.util.Stack;
-
-/**
- * The Stack class in java.util (most unhelpfully) does not implement the Queue interface. This is an adaption of that
- * class as a queue.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Turn a stack into a queue.
- * </table>
- *
- * @todo Need to override the add method, and iterator and consider other methods too. They work like LIFO but
- * really wany FIFO behaviour accross the whole data structure.
- *
- * @author Rupert Smith
- */
-public class StackQueue<E> extends Stack<E> implements Queue<E>
-{
- /**
- * Retrieves, but does not remove, the head of this queue.
- *
- * @return The element at the top of the stack.
- */
- public E element()
- {
- try
- {
- return super.peek();
- }
- catch (EmptyStackException e)
- {
- NoSuchElementException t = new NoSuchElementException();
- t.initCause(e);
- throw t;
- }
- }
-
- /**
- * Inserts the specified element into this queue, if possible.
- *
- * @param o The data element to push onto the stack.
- *
- * @return True if it was added to the stack, false otherwise (this implementation always returns true).
- */
- public boolean offer(E o)
- {
- push(o);
-
- return true;
- }
-
- /**
- * Retrieves, but does not remove, the head of this queue, returning null if this queue is empty.
- *
- * @return The top element from the stack, or null if the stack is empty.
- */
- public E peek()
- {
- try
- {
- return super.peek();
- }
- catch (EmptyStackException e)
- {
- return null;
- }
- }
-
- /**
- * Retrieves and removes the head of this queue, or null if this queue is empty.
- *
- * @return The top element from the stack, or null if the stack is empty.
- */
- public E poll()
- {
- try
- {
- return super.pop();
- }
- catch (EmptyStackException e)
- {
- return null;
- }
- }
-
- /**
- * Retrieves and removes the head of this queue.
- *
- * @return The top element from the stack, or null if the stack is empty.
- *
- * @throws NoSuchElementException If the stack is empty so no element can be removed from it.
- */
- public E remove()
- {
- try
- {
- return super.pop();
- }
- catch (EmptyStackException e)
- {
- NoSuchElementException t = new NoSuchElementException();
- t.initCause(e);
- throw t;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.util.EmptyStackException;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Stack;
+
+/**
+ * The Stack class in java.util (most unhelpfully) does not implement the Queue interface. This is an adaption of that
+ * class as a queue.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Turn a stack into a queue.
+ * </table>
+ *
+ * @todo Need to override the add method, and iterator and consider other methods too. They work like LIFO but
+ * really wany FIFO behaviour accross the whole data structure.
+ *
+ * @author Rupert Smith
+ */
+public class StackQueue<E> extends Stack<E> implements Queue<E>
+{
+ /**
+ * Retrieves, but does not remove, the head of this queue.
+ *
+ * @return The element at the top of the stack.
+ */
+ public E element()
+ {
+ try
+ {
+ return super.peek();
+ }
+ catch (EmptyStackException e)
+ {
+ NoSuchElementException t = new NoSuchElementException();
+ t.initCause(e);
+ throw t;
+ }
+ }
+
+ /**
+ * Inserts the specified element into this queue, if possible.
+ *
+ * @param o The data element to push onto the stack.
+ *
+ * @return True if it was added to the stack, false otherwise (this implementation always returns true).
+ */
+ public boolean offer(E o)
+ {
+ push(o);
+
+ return true;
+ }
+
+ /**
+ * Retrieves, but does not remove, the head of this queue, returning null if this queue is empty.
+ *
+ * @return The top element from the stack, or null if the stack is empty.
+ */
+ public E peek()
+ {
+ try
+ {
+ return super.peek();
+ }
+ catch (EmptyStackException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue, or null if this queue is empty.
+ *
+ * @return The top element from the stack, or null if the stack is empty.
+ */
+ public E poll()
+ {
+ try
+ {
+ return super.pop();
+ }
+ catch (EmptyStackException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Retrieves and removes the head of this queue.
+ *
+ * @return The top element from the stack, or null if the stack is empty.
+ *
+ * @throws NoSuchElementException If the stack is empty so no element can be removed from it.
+ */
+ public E remove()
+ {
+ try
+ {
+ return super.pop();
+ }
+ catch (EmptyStackException e)
+ {
+ NoSuchElementException t = new NoSuchElementException();
+ t.initCause(e);
+ throw t;
+ }
+ }
+}
diff --git a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java
index edb7b6d73a..d402077963 100644
--- a/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java
+++ b/qpid/java/junit-toolkit/src/main/org/apache/qpid/junit/extensions/util/TestContextProperties.java
@@ -1,202 +1,202 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.junit.extensions.util;
-
-import java.util.Properties;
-
-/**
- * TestContextProperties is an extension of {@link ParsedProperties} that keeps track of property key/value pairs
- * that are used by tests being run under the {@link org.apache.qpid.junit.extensions.TKTestRunner}. To keep the
- * test runner notified of configurable test parameters, tests should establish their required property values by
- * initiliazing fields or statics or in the constructor, through this class. The tk test runner automatically places
- * any additional properties specified on the command line into the this class, and these are held statically.
- *
- * <p/>Here is an example:
- *
- * <pre>
- * public class MyTestClass extends TestCase {
- * ParsedProperties testProps = TestContextProperties.getInstance();
- * private int testParam = testProps.setPropertyIfNull("testParam", 1);
- * ...
- * </pre>
- *
- * <p/>This has the effect of setting up the field testParam with the default value of 1, unless it is overridden
- * by values passed to the tk test runner. It also notifies the tk test runner of the name and value of the test
- * parameter actually used for the test, so that this can be logged in the test output file.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Log all name/value pairs read or written.
- * </table>
- *
- * @author Rupert Smith
- */
-public class TestContextProperties extends ParsedProperties
-{
- /** Used for debugging. */
- // Logger log = Logger.getLogger(TestContextProperties.class);
-
- /** Holds all properties set or read through this property extension class. */
- private Properties accessedProps = new Properties();
-
- /** The singleton instance of the test context properties. */
- private static TestContextProperties singleton = null;
-
- /**
- * Default constructor that builds a ContextualProperties that uses environment defaults.
- */
- private TestContextProperties()
- {
- super();
- }
-
- /**
- * Gets the singleton instance of the test context properties.
- *
- * @return The singleton instance of the test context properties.
- */
- public static synchronized ParsedProperties getInstance()
- {
- if (singleton == null)
- {
- singleton = new TestContextProperties();
- }
-
- return singleton;
- }
-
- /**
- * Gets the singleton instance of the test context properties, applying a specified set of default properties to
- * it, if they are not already set.
- *
- * @param defaults The defaults to apply for properties not already set.
- *
- * @return The singleton instance of the test context properties.
- */
- public static synchronized ParsedProperties getInstance(Properties defaults)
- {
- ParsedProperties props = getInstance();
-
- for (Object key : defaults.keySet())
- {
- String stringKey = (String) key;
- String value = defaults.getProperty(stringKey);
-
- props.setPropertyIfNull(stringKey, value);
- }
-
- return props;
- }
-
- /*
- * Creates a ContextualProperties that uses environment defaults and is initialized with the specified properties.
- *
- * @param props The properties to initialize this with.
- */
- /*public TestContextProperties(Properties props)
- {
- super();
- }*/
-
- /**
- * Gets all of the properties (with their most recent values) that have been set or read through this class.
- *
- * @return All of the properties accessed through this class.
- */
- public static Properties getAccessedProps()
- {
- return (singleton == null) ? new Properties() : singleton;
- // return accessedProps;
- }
-
- /**
- * Looks up a property value relative to the environment, callers class and method. The default environment will be
- * checked for a matching property if defaults are being used. The property key/value pair is remembered and made
- * available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
- *
- * @param key The property key.
- *
- * @return The value of this property searching from the most specific definition (environment, class, method, key)
- * to the most general (key only), unless use of default environments is turned off in which case the most general
- * proeprty searched is (environment, key).
- */
- public String getProperty(String key)
- {
- // log.debug("public String getProperty(String key = " + key + "): called");
-
- String value = super.getProperty(key);
-
- if (value != null)
- {
- accessedProps.setProperty(key, value);
- }
-
- // log.debug("value = " + value);
-
- return value;
- }
-
- /**
- * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for parallelism with the <tt>getProperty</tt>
- * method. Enforces use of strings for property keys and values. The value returned is the result of the
- * <tt>Hashtable</tt> call to <code>put</code>. The property key/value pair is remembered and made
- * available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
- *
- * @param key The key to be placed into this property list.
- * @param value The value corresponding to <tt>key</tt>.
- *
- * @return The previous value of the specified key in this property list, or <code>null</code> if it did not have one.
- */
- public synchronized Object setProperty(String key, String value)
- {
- // log.debug("public synchronized Object setProperty(String key = " + key + ", String value = " + value + "): called");
-
- Object result = super.setProperty(key, value);
- accessedProps.setProperty(key, value);
-
- return result;
- }
-
- /**
- * Helper method for setting properties to defaults when they are not already set. The property key/value pair is
- * remembered and made available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
- *
- * @param key The name of the system property to set.
- * @param value The value to set it to.
- *
- * @return The value of the property, which will be the value passed in if it was null, or the existing value otherwise.
- */
- public String setPropertyIfNull(String key, String value)
- {
- // log.debug("public String setPropertyIfNull(String key = " + key + ", String value = " + value + "): called");
-
- String result = super.setPropertyIfNull(key, value);
-
- if (value != null)
- {
- accessedProps.setProperty(key, result);
- }
-
- // log.debug("result = " + result);
-
- return result;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.junit.extensions.util;
+
+import java.util.Properties;
+
+/**
+ * TestContextProperties is an extension of {@link ParsedProperties} that keeps track of property key/value pairs
+ * that are used by tests being run under the {@link org.apache.qpid.junit.extensions.TKTestRunner}. To keep the
+ * test runner notified of configurable test parameters, tests should establish their required property values by
+ * initiliazing fields or statics or in the constructor, through this class. The tk test runner automatically places
+ * any additional properties specified on the command line into the this class, and these are held statically.
+ *
+ * <p/>Here is an example:
+ *
+ * <pre>
+ * public class MyTestClass extends TestCase {
+ * ParsedProperties testProps = TestContextProperties.getInstance();
+ * private int testParam = testProps.setPropertyIfNull("testParam", 1);
+ * ...
+ * </pre>
+ *
+ * <p/>This has the effect of setting up the field testParam with the default value of 1, unless it is overridden
+ * by values passed to the tk test runner. It also notifies the tk test runner of the name and value of the test
+ * parameter actually used for the test, so that this can be logged in the test output file.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Log all name/value pairs read or written.
+ * </table>
+ *
+ * @author Rupert Smith
+ */
+public class TestContextProperties extends ParsedProperties
+{
+ /** Used for debugging. */
+ // Logger log = Logger.getLogger(TestContextProperties.class);
+
+ /** Holds all properties set or read through this property extension class. */
+ private Properties accessedProps = new Properties();
+
+ /** The singleton instance of the test context properties. */
+ private static TestContextProperties singleton = null;
+
+ /**
+ * Default constructor that builds a ContextualProperties that uses environment defaults.
+ */
+ private TestContextProperties()
+ {
+ super();
+ }
+
+ /**
+ * Gets the singleton instance of the test context properties.
+ *
+ * @return The singleton instance of the test context properties.
+ */
+ public static synchronized ParsedProperties getInstance()
+ {
+ if (singleton == null)
+ {
+ singleton = new TestContextProperties();
+ }
+
+ return singleton;
+ }
+
+ /**
+ * Gets the singleton instance of the test context properties, applying a specified set of default properties to
+ * it, if they are not already set.
+ *
+ * @param defaults The defaults to apply for properties not already set.
+ *
+ * @return The singleton instance of the test context properties.
+ */
+ public static synchronized ParsedProperties getInstance(Properties defaults)
+ {
+ ParsedProperties props = getInstance();
+
+ for (Object key : defaults.keySet())
+ {
+ String stringKey = (String) key;
+ String value = defaults.getProperty(stringKey);
+
+ props.setPropertyIfNull(stringKey, value);
+ }
+
+ return props;
+ }
+
+ /*
+ * Creates a ContextualProperties that uses environment defaults and is initialized with the specified properties.
+ *
+ * @param props The properties to initialize this with.
+ */
+ /*public TestContextProperties(Properties props)
+ {
+ super();
+ }*/
+
+ /**
+ * Gets all of the properties (with their most recent values) that have been set or read through this class.
+ *
+ * @return All of the properties accessed through this class.
+ */
+ public static Properties getAccessedProps()
+ {
+ return (singleton == null) ? new Properties() : singleton;
+ // return accessedProps;
+ }
+
+ /**
+ * Looks up a property value relative to the environment, callers class and method. The default environment will be
+ * checked for a matching property if defaults are being used. The property key/value pair is remembered and made
+ * available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
+ *
+ * @param key The property key.
+ *
+ * @return The value of this property searching from the most specific definition (environment, class, method, key)
+ * to the most general (key only), unless use of default environments is turned off in which case the most general
+ * proeprty searched is (environment, key).
+ */
+ public String getProperty(String key)
+ {
+ // log.debug("public String getProperty(String key = " + key + "): called");
+
+ String value = super.getProperty(key);
+
+ if (value != null)
+ {
+ accessedProps.setProperty(key, value);
+ }
+
+ // log.debug("value = " + value);
+
+ return value;
+ }
+
+ /**
+ * Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for parallelism with the <tt>getProperty</tt>
+ * method. Enforces use of strings for property keys and values. The value returned is the result of the
+ * <tt>Hashtable</tt> call to <code>put</code>. The property key/value pair is remembered and made
+ * available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
+ *
+ * @param key The key to be placed into this property list.
+ * @param value The value corresponding to <tt>key</tt>.
+ *
+ * @return The previous value of the specified key in this property list, or <code>null</code> if it did not have one.
+ */
+ public synchronized Object setProperty(String key, String value)
+ {
+ // log.debug("public synchronized Object setProperty(String key = " + key + ", String value = " + value + "): called");
+
+ Object result = super.setProperty(key, value);
+ accessedProps.setProperty(key, value);
+
+ return result;
+ }
+
+ /**
+ * Helper method for setting properties to defaults when they are not already set. The property key/value pair is
+ * remembered and made available to {@link org.apache.qpid.junit.extensions.TKTestRunner}.
+ *
+ * @param key The name of the system property to set.
+ * @param value The value to set it to.
+ *
+ * @return The value of the property, which will be the value passed in if it was null, or the existing value otherwise.
+ */
+ public String setPropertyIfNull(String key, String value)
+ {
+ // log.debug("public String setPropertyIfNull(String key = " + key + ", String value = " + value + "): called");
+
+ String result = super.setPropertyIfNull(key, value);
+
+ if (value != null)
+ {
+ accessedProps.setProperty(key, result);
+ }
+
+ // log.debug("result = " + result);
+
+ return result;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java
index b9632eee4c..0afec83b19 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingClient.java
@@ -1,107 +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.ping;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.requestreply.PingPongProducer;
-
-import javax.jms.Destination;
-
-import java.util.List;
-import java.util.Properties;
-
-/**
- * PingClient is a {@link PingPongProducer} that does not need a {@link org.apache.qpid.requestreply.PingPongBouncer}
- * to send replies to its pings. It simply listens to its own ping destinations, rather than seperate reply queues.
- * It is an all in one ping client, that produces and consumes its own pings.
- *
- * <p/>The constructor increments a count of the number of ping clients created. It is assumed that where many
- * are created they will all be run in parallel and be active in sending and consuming pings at the same time.
- * If the unique destinations flag is not set and a pub/sub ping cycle is being run, this means that they will all hear
- * pings sent by each other. The expected number of pings received will therefore be multiplied up by the number of
- * active ping clients. The {@link #getConsumersPerDestination()} method is used to supply this multiplier under these
- * conditions.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Create a ping producer that listens to its own pings <td> {@link PingPongProducer}
- * <tr><td> Count the number of ping producers and produce multiplier for scaling up messages expected over topic pings.
- * </table>
- */
-public class PingClient extends PingPongProducer
-{
- /** Used for debugging. */
- private final Logger log = Logger.getLogger(PingClient.class);
-
- /** Used to count the number of ping clients created. */
- private static int _pingClientCount;
-
- /**
- * Creates a ping producer with the specified parameters, of which there are many. See the class level comments
- * for {@link PingPongProducer} for details. This constructor creates a connection to the broker and creates
- * producer and consumer sessions on it, to send and recieve its pings and replies on.
- *
- * @param overrides Properties containing any desired overrides to the defaults.
- *
- * @throws Exception Any exceptions are allowed to fall through.
- */
- public PingClient(Properties overrides) throws Exception
- {
- super(overrides);
-
- _pingClientCount++;
- }
-
- /**
- * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the
- * effect of making this pinger listen to its own pings.
- *
- * @return The ping destinations.
- */
- public List<Destination> getReplyDestinations()
- {
- return _pingDestinations;
- }
-
- /**
- * Supplies the multiplier for the number of ping clients that will hear each ping when doing pub/sub pinging.
- *
- * @return The scaling up of the number of expected pub/sub pings.
- */
- public int getConsumersPerDestination()
- {
- log.debug("public int getConsumersPerDestination(): called");
-
- if (_isUnique)
- {
- log.debug(_noOfConsumers + " consumer per destination.");
-
- return _noOfConsumers;
- }
- else
- {
- log.debug((_pingClientCount * _noOfConsumers) + " consumers per destination.");
-
- return _pingClientCount * _noOfConsumers;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.ping;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.requestreply.PingPongProducer;
+
+import javax.jms.Destination;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * PingClient is a {@link PingPongProducer} that does not need a {@link org.apache.qpid.requestreply.PingPongBouncer}
+ * to send replies to its pings. It simply listens to its own ping destinations, rather than seperate reply queues.
+ * It is an all in one ping client, that produces and consumes its own pings.
+ *
+ * <p/>The constructor increments a count of the number of ping clients created. It is assumed that where many
+ * are created they will all be run in parallel and be active in sending and consuming pings at the same time.
+ * If the unique destinations flag is not set and a pub/sub ping cycle is being run, this means that they will all hear
+ * pings sent by each other. The expected number of pings received will therefore be multiplied up by the number of
+ * active ping clients. The {@link #getConsumersPerDestination()} method is used to supply this multiplier under these
+ * conditions.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create a ping producer that listens to its own pings <td> {@link PingPongProducer}
+ * <tr><td> Count the number of ping producers and produce multiplier for scaling up messages expected over topic pings.
+ * </table>
+ */
+public class PingClient extends PingPongProducer
+{
+ /** Used for debugging. */
+ private final Logger log = Logger.getLogger(PingClient.class);
+
+ /** Used to count the number of ping clients created. */
+ private static int _pingClientCount;
+
+ /**
+ * Creates a ping producer with the specified parameters, of which there are many. See the class level comments
+ * for {@link PingPongProducer} for details. This constructor creates a connection to the broker and creates
+ * producer and consumer sessions on it, to send and recieve its pings and replies on.
+ *
+ * @param overrides Properties containing any desired overrides to the defaults.
+ *
+ * @throws Exception Any exceptions are allowed to fall through.
+ */
+ public PingClient(Properties overrides) throws Exception
+ {
+ super(overrides);
+
+ _pingClientCount++;
+ }
+
+ /**
+ * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the
+ * effect of making this pinger listen to its own pings.
+ *
+ * @return The ping destinations.
+ */
+ public List<Destination> getReplyDestinations()
+ {
+ return _pingDestinations;
+ }
+
+ /**
+ * Supplies the multiplier for the number of ping clients that will hear each ping when doing pub/sub pinging.
+ *
+ * @return The scaling up of the number of expected pub/sub pings.
+ */
+ public int getConsumersPerDestination()
+ {
+ log.debug("public int getConsumersPerDestination(): called");
+
+ if (_isUnique)
+ {
+ log.debug(_noOfConsumers + " consumer per destination.");
+
+ return _noOfConsumers;
+ }
+ else
+ {
+ log.debug((_pingClientCount * _noOfConsumers) + " consumers per destination.");
+
+ return _pingClientCount * _noOfConsumers;
+ }
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
index 0c8c19243a..a15897c82b 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java
@@ -1,452 +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.ping;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.requestreply.PingPongProducer;
-import org.apache.qpid.util.CommandLineParser;
-
-import org.apache.qpid.junit.extensions.util.MathUtils;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.*;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * PingDurableClient is a variation of the {@link PingPongProducer} ping tool. Instead of sending its pings and
- * receiving replies to them at the same time, this tool sends pings until it is signalled by some 'event' to stop
- * sending. It then waits for another signal before it re-opens a fresh connection and attempts to receive all of the
- * pings that it has succesfully sent. It is intended to be an interactive test that lets a user experiment with
- * failure conditions when using durable messaging.
- *
- * <p/>The events that can stop it from sending are input from the user on the console, failure of its connection to
- * the broker, completion of sending a specified number of messages, or expiry of a specified duration. In all cases
- * it will do its best to clean up and close the connection before opening a fresh connection to receive the pings
- * with.
- *
- * <p/>The event to re-connect and attempt to recieve the pings is input from the user on the console.
- *
- * <p/>This ping client inherits the configuration properties of its parent class ({@link PingPongProducer}) and
- * additionally accepts the following parameters:
- *
- * <p/><table><caption>Parameters</caption>
- * <tr><th> Parameter <th> Default <th> Comments
- * <tr><td> numMessages <td> 100 <td> The total number of messages to send.
- * <tr><td> numMessagesToAction <td> -1 <td> The number of messages to send before taking a custom 'action'.
- * <tr><td> duration <td> 30S <td> The length of time to ping for. (Format dDhHmMsS, for d days, h hours,
- * m minutes and s seconds).
- * </table>
- *
- * <p/>This ping client also overrides some of the defaults of its parent class, to provide a reasonable set up
- * when no parameters are specified.
- *
- * <p/><table><caption>Parameters</caption>
- * <tr><th> Parameter <th> Default <th> Comments
- * <tr><td> uniqueDests <td> false <td> Prevents destination names being timestamped.
- * <tr><td> transacted <td> true <td> Only makes sense to test with transactions.
- * <tr><td> persistent <td> true <td> Only makes sense to test persistent.
- * <tr><td> durableDests <td> true <td> Should use durable queues with persistent messages.
- * <tr><td> commitBatchSize <td> 10
- * <tr><td> rate <td> 20 <td> Total default test time is 5 seconds.
- * </table>
- *
- * <p/>When a number of messages or duration is specified, this ping client will ping until the first of those limits
- * is reached. Reaching the limit will be interpreted as the first signal to stop sending, and the ping client will
- * wait for the second signal before receiving its pings.
- *
- * <p/>This class provides a mechanism for extensions to add arbitrary actions, after a particular number of messages
- * have been sent. When the number of messages equal the value set in the 'numMessagesToAction' property is method,
- * the {@link #takeAction} method is called. By default this does nothing, but extensions of this class can provide
- * custom behaviour with alternative implementations of this method (for example taking a backup).
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Send and receive pings.
- * <tr><td> Accept user input to signal stop sending.
- * <tr><td> Accept user input to signal start receiving.
- * <tr><td> Provide feedback on pings sent versus pings received.
- * <tr><td> Provide extension point for arbitrary action on a particular message count.
- * </table>
- */
-public class PingDurableClient extends PingPongProducer implements ExceptionListener
-{
- private static final Logger log = Logger.getLogger(PingDurableClient.class);
-
- public static final String NUM_MESSAGES_PROPNAME = "numMessages";
- public static final String NUM_MESSAGES_DEFAULT = "100";
- public static final String DURATION_PROPNAME = "duration";
- public static final String DURATION_DEFAULT = "30S";
- public static final String NUM_MESSAGES_TO_ACTION_PROPNAME = "numMessagesToAction";
- public static final String NUM_MESSAGES_TO_ACTION_DEFAULT = "-1";
-
- /** The maximum length of time to wait whilst receiving pings before assuming that no more are coming. */
- private static final long TIME_OUT = 3000;
-
- static
- {
- defaults.setProperty(NUM_MESSAGES_PROPNAME, NUM_MESSAGES_DEFAULT);
- defaults.setProperty(DURATION_PROPNAME, DURATION_DEFAULT);
- defaults.setProperty(UNIQUE_DESTS_PROPNAME, "false");
- defaults.setProperty(TRANSACTED_PROPNAME, "true");
- defaults.setProperty(PERSISTENT_MODE_PROPNAME, "true");
- defaults.setProperty(TX_BATCH_SIZE_PROPNAME, "10");
- defaults.setProperty(RATE_PROPNAME, "20");
- defaults.setProperty(DURABLE_DESTS_PROPNAME, "true");
- defaults.setProperty(NUM_MESSAGES_TO_ACTION_PROPNAME, NUM_MESSAGES_TO_ACTION_DEFAULT);
- }
-
- /** Specifies the number of pings to send, if larger than 0. 0 means send until told to stop. */
- private int numMessages;
-
- /** Holds the number of messages to send before taking triggering the action. */
- private int numMessagesToAction;
-
- /** Sepcifies how long to ping for, if larger than 0. 0 means send until told to stop. */
- private long duration;
-
- /** Used to indciate that this application should terminate. Set by the shutdown hook. */
- private boolean terminate = false;
-
- /**
- * @throws Exception Any exceptions are allowed to fall through.
- */
- public PingDurableClient(Properties overrides) throws Exception
- {
- super(overrides);
- log.debug("public PingDurableClient(Properties overrides = " + overrides + "): called");
-
- // Extract the additional configuration parameters.
- ParsedProperties properties = new ParsedProperties(defaults);
- properties.putAll(overrides);
-
- numMessages = properties.getPropertyAsInteger(NUM_MESSAGES_PROPNAME);
- String durationSpec = properties.getProperty(DURATION_PROPNAME);
- numMessagesToAction = properties.getPropertyAsInteger(NUM_MESSAGES_TO_ACTION_PROPNAME);
-
- if (durationSpec != null)
- {
- duration = MathUtils.parseDuration(durationSpec) * 1000000;
- }
- }
-
- /**
- * Starts the ping/wait/receive process.
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- try
- {
- // Create a ping producer overriding its defaults with all options passed on the command line.
- Properties options =
- CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
- PingDurableClient pingProducer = new PingDurableClient(options);
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
-
- // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
- // pingProducer.getConnection().setExceptionListener(pingProducer);
-
- // Run the test procedure.
- int sent = pingProducer.send();
- pingProducer.closeConnection();
- pingProducer.waitForUser("Press return to begin receiving the pings.");
- pingProducer.receive(sent);
-
- System.exit(0);
- }
- catch (Exception e)
- {
- System.err.println(e.getMessage());
- log.error("Top level handler caught execption.", e);
- System.exit(1);
- }
- }
-
- /**
- * Performs the main test procedure implemented by this ping client. See the class level comment for details.
- */
- protected int send() throws Exception
- {
- log.debug("public void sendWaitReceive(): called");
-
- log.debug("duration = " + duration);
- log.debug("numMessages = " + numMessages);
-
- if (duration > 0)
- {
- System.out.println("Sending for up to " + (duration / 1000000000f) + " seconds.");
- }
-
- if (_rate > 0)
- {
- System.out.println("Sending at " + _rate + " messages per second.");
- }
-
- if (numMessages > 0)
- {
- System.out.println("Sending up to " + numMessages + " messages.");
- }
-
- // Establish the connection and the message producer.
- establishConnection(true, false);
- _connection.start();
-
- Message message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent);
-
- // Send pings until a terminating condition is received.
- boolean endCondition = false;
- int messagesSent = 0;
- int messagesCommitted = 0;
- int messagesNotCommitted = 0;
- long start = System.nanoTime();
-
- // Clear console in.
- clearConsole();
-
- while (!endCondition)
- {
- boolean committed = false;
-
- try
- {
- committed = sendMessage(messagesSent, message) && _transacted;
-
- messagesSent++;
- messagesNotCommitted++;
-
- // Keep count of the number of messsages currently committed and pending commit.
- if (committed)
- {
- log.debug("Adding " + messagesNotCommitted + " messages to the committed count.");
- messagesCommitted += messagesNotCommitted;
- messagesNotCommitted = 0;
-
- System.out.println("Commited: " + messagesCommitted);
- }
- }
- catch (JMSException e)
- {
- log.debug("Got JMSException whilst sending.");
- _publish = false;
- }
-
- // Perform the arbitrary action if the number of messages sent has reached the right number.
- if (messagesSent == numMessagesToAction)
- {
- System.out.println("At action point, Messages sent = " + messagesSent + ", Messages Committed = "
- + messagesCommitted + ", Messages not Committed = " + messagesNotCommitted);
- takeAction();
- }
-
- // Determine if the end condition has been met, based on the number of messages, time passed, errors on
- // the connection or user input.
- long now = System.nanoTime();
-
- if ((duration != 0) && ((now - start) > duration))
- {
- System.out.println("Send halted because duration expired.");
- endCondition = true;
- }
- else if ((numMessages != 0) && (messagesSent >= numMessages))
- {
- System.out.println("Send halted because # messages completed.");
- endCondition = true;
- }
- else if (System.in.available() > 0)
- {
- System.out.println("Send halted by user input.");
- endCondition = true;
-
- clearConsole();
- }
- else if (!_publish)
- {
- System.out.println("Send halted by error on the connection.");
- endCondition = true;
- }
- }
-
- log.debug("messagesSent = " + messagesSent);
- log.debug("messagesCommitted = " + messagesCommitted);
- log.debug("messagesNotCommitted = " + messagesNotCommitted);
-
- System.out.println("Messages sent: " + messagesSent + ", Messages Committed = " + messagesCommitted
- + ", Messages not Committed = " + messagesNotCommitted);
-
- return messagesSent;
- }
-
- protected void closeConnection()
- {
- // Clean up the connection.
- try
- {
- close();
- }
- catch (JMSException e)
- {
- log.debug("There was an error whilst closing the connection: " + e, e);
- System.out.println("There was an error whilst closing the connection.");
-
- // Ignore as did best could manage to clean up.
- }
- }
-
- protected void receive(int messagesSent) throws Exception
- {
- // Re-establish the connection and the message consumer.
- _queueJVMSequenceID = new AtomicInteger();
- _queueSharedID = new AtomicInteger();
-
- establishConnection(false, true);
- _consumer[0].setMessageListener(null);
- _consumerConnection[0].start();
-
- // Try to receive all of the pings that were successfully sent.
- int messagesReceived = 0;
- boolean endCondition = false;
-
- while (!endCondition)
- {
- // Message received = _consumer.receiveNoWait();
- Message received = _consumer[0].receive(TIME_OUT);
- log.debug("received = " + received);
-
- if (received != null)
- {
- messagesReceived++;
- }
-
- // Determine if the end condition has been met, based on the number of messages and time passed since last
- // receiving a message.
- if (received == null)
- {
- System.out.println("Timed out.");
- endCondition = true;
- }
- else if (messagesReceived >= messagesSent)
- {
- System.out.println("Got all messages.");
- endCondition = true;
- }
- }
-
- // Ensure messages received are committed.
- if (_consTransacted)
- {
- try
- {
- _consumerSession[0].commit();
- System.out.println("Committed for all messages received.");
- }
- catch (JMSException e)
- {
- log.debug("Error during commit: " + e, e);
- System.out.println("Error during commit.");
- try
- {
- _consumerSession[0].rollback();
- System.out.println("Rolled back on all messages received.");
- }
- catch (JMSException e2)
- {
- log.debug("Error during rollback: " + e, e);
- System.out.println("Error on roll back of all messages received.");
- }
-
- }
- }
-
- log.debug("messagesReceived = " + messagesReceived);
-
- System.out.println("Messages received: " + messagesReceived);
-
- // Clean up the connection.
- close();
- }
-
- /**
- * Clears any pending input from the console.
- */
- private void clearConsole()
- {
- try
- {
- BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
-
- // System.in.skip(System.in.available());
- while (bis.ready())
- {
- bis.readLine();
- }
- }
- catch (IOException e)
- { }
- }
-
- /**
- * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the
- * effect of making this pinger listen to its own pings.
- *
- * @return The ping destinations.
- */
- public List<Destination> getReplyDestinations()
- {
- return _pingDestinations;
- }
-
- /**
- * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered with
- * the runtime system as a shutdown hook. This shutdown hook sets an additional terminate flag, compared with the
- * shutdown hook in {@link PingPongProducer}, because the publish flag is used to indicate that sending or receiving
- * message should stop, not that the application should termiante.
- *
- * @return A shutdown hook for the ping loop.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- stop();
- terminate = true;
- }
- });
- }
-
- /**
- * Performs an aribtrary action once the 'numMesagesToAction' count is reached on sending messages. This default
- * implementation does nothing.
- */
- public void takeAction()
- { }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.ping;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.requestreply.PingPongProducer;
+import org.apache.qpid.util.CommandLineParser;
+
+import org.apache.qpid.junit.extensions.util.MathUtils;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * PingDurableClient is a variation of the {@link PingPongProducer} ping tool. Instead of sending its pings and
+ * receiving replies to them at the same time, this tool sends pings until it is signalled by some 'event' to stop
+ * sending. It then waits for another signal before it re-opens a fresh connection and attempts to receive all of the
+ * pings that it has succesfully sent. It is intended to be an interactive test that lets a user experiment with
+ * failure conditions when using durable messaging.
+ *
+ * <p/>The events that can stop it from sending are input from the user on the console, failure of its connection to
+ * the broker, completion of sending a specified number of messages, or expiry of a specified duration. In all cases
+ * it will do its best to clean up and close the connection before opening a fresh connection to receive the pings
+ * with.
+ *
+ * <p/>The event to re-connect and attempt to recieve the pings is input from the user on the console.
+ *
+ * <p/>This ping client inherits the configuration properties of its parent class ({@link PingPongProducer}) and
+ * additionally accepts the following parameters:
+ *
+ * <p/><table><caption>Parameters</caption>
+ * <tr><th> Parameter <th> Default <th> Comments
+ * <tr><td> numMessages <td> 100 <td> The total number of messages to send.
+ * <tr><td> numMessagesToAction <td> -1 <td> The number of messages to send before taking a custom 'action'.
+ * <tr><td> duration <td> 30S <td> The length of time to ping for. (Format dDhHmMsS, for d days, h hours,
+ * m minutes and s seconds).
+ * </table>
+ *
+ * <p/>This ping client also overrides some of the defaults of its parent class, to provide a reasonable set up
+ * when no parameters are specified.
+ *
+ * <p/><table><caption>Parameters</caption>
+ * <tr><th> Parameter <th> Default <th> Comments
+ * <tr><td> uniqueDests <td> false <td> Prevents destination names being timestamped.
+ * <tr><td> transacted <td> true <td> Only makes sense to test with transactions.
+ * <tr><td> persistent <td> true <td> Only makes sense to test persistent.
+ * <tr><td> durableDests <td> true <td> Should use durable queues with persistent messages.
+ * <tr><td> commitBatchSize <td> 10
+ * <tr><td> rate <td> 20 <td> Total default test time is 5 seconds.
+ * </table>
+ *
+ * <p/>When a number of messages or duration is specified, this ping client will ping until the first of those limits
+ * is reached. Reaching the limit will be interpreted as the first signal to stop sending, and the ping client will
+ * wait for the second signal before receiving its pings.
+ *
+ * <p/>This class provides a mechanism for extensions to add arbitrary actions, after a particular number of messages
+ * have been sent. When the number of messages equal the value set in the 'numMessagesToAction' property is method,
+ * the {@link #takeAction} method is called. By default this does nothing, but extensions of this class can provide
+ * custom behaviour with alternative implementations of this method (for example taking a backup).
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Send and receive pings.
+ * <tr><td> Accept user input to signal stop sending.
+ * <tr><td> Accept user input to signal start receiving.
+ * <tr><td> Provide feedback on pings sent versus pings received.
+ * <tr><td> Provide extension point for arbitrary action on a particular message count.
+ * </table>
+ */
+public class PingDurableClient extends PingPongProducer implements ExceptionListener
+{
+ private static final Logger log = Logger.getLogger(PingDurableClient.class);
+
+ public static final String NUM_MESSAGES_PROPNAME = "numMessages";
+ public static final String NUM_MESSAGES_DEFAULT = "100";
+ public static final String DURATION_PROPNAME = "duration";
+ public static final String DURATION_DEFAULT = "30S";
+ public static final String NUM_MESSAGES_TO_ACTION_PROPNAME = "numMessagesToAction";
+ public static final String NUM_MESSAGES_TO_ACTION_DEFAULT = "-1";
+
+ /** The maximum length of time to wait whilst receiving pings before assuming that no more are coming. */
+ private static final long TIME_OUT = 3000;
+
+ static
+ {
+ defaults.setProperty(NUM_MESSAGES_PROPNAME, NUM_MESSAGES_DEFAULT);
+ defaults.setProperty(DURATION_PROPNAME, DURATION_DEFAULT);
+ defaults.setProperty(UNIQUE_DESTS_PROPNAME, "false");
+ defaults.setProperty(TRANSACTED_PROPNAME, "true");
+ defaults.setProperty(PERSISTENT_MODE_PROPNAME, "true");
+ defaults.setProperty(TX_BATCH_SIZE_PROPNAME, "10");
+ defaults.setProperty(RATE_PROPNAME, "20");
+ defaults.setProperty(DURABLE_DESTS_PROPNAME, "true");
+ defaults.setProperty(NUM_MESSAGES_TO_ACTION_PROPNAME, NUM_MESSAGES_TO_ACTION_DEFAULT);
+ }
+
+ /** Specifies the number of pings to send, if larger than 0. 0 means send until told to stop. */
+ private int numMessages;
+
+ /** Holds the number of messages to send before taking triggering the action. */
+ private int numMessagesToAction;
+
+ /** Sepcifies how long to ping for, if larger than 0. 0 means send until told to stop. */
+ private long duration;
+
+ /** Used to indciate that this application should terminate. Set by the shutdown hook. */
+ private boolean terminate = false;
+
+ /**
+ * @throws Exception Any exceptions are allowed to fall through.
+ */
+ public PingDurableClient(Properties overrides) throws Exception
+ {
+ super(overrides);
+ log.debug("public PingDurableClient(Properties overrides = " + overrides + "): called");
+
+ // Extract the additional configuration parameters.
+ ParsedProperties properties = new ParsedProperties(defaults);
+ properties.putAll(overrides);
+
+ numMessages = properties.getPropertyAsInteger(NUM_MESSAGES_PROPNAME);
+ String durationSpec = properties.getProperty(DURATION_PROPNAME);
+ numMessagesToAction = properties.getPropertyAsInteger(NUM_MESSAGES_TO_ACTION_PROPNAME);
+
+ if (durationSpec != null)
+ {
+ duration = MathUtils.parseDuration(durationSpec) * 1000000;
+ }
+ }
+
+ /**
+ * Starts the ping/wait/receive process.
+ *
+ * @param args The command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ // Create a ping producer overriding its defaults with all options passed on the command line.
+ Properties options =
+ CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
+ PingDurableClient pingProducer = new PingDurableClient(options);
+
+ // Create a shutdown hook to terminate the ping-pong producer.
+ Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
+
+ // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
+ // pingProducer.getConnection().setExceptionListener(pingProducer);
+
+ // Run the test procedure.
+ int sent = pingProducer.send();
+ pingProducer.closeConnection();
+ pingProducer.waitForUser("Press return to begin receiving the pings.");
+ pingProducer.receive(sent);
+
+ System.exit(0);
+ }
+ catch (Exception e)
+ {
+ System.err.println(e.getMessage());
+ log.error("Top level handler caught execption.", e);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Performs the main test procedure implemented by this ping client. See the class level comment for details.
+ */
+ protected int send() throws Exception
+ {
+ log.debug("public void sendWaitReceive(): called");
+
+ log.debug("duration = " + duration);
+ log.debug("numMessages = " + numMessages);
+
+ if (duration > 0)
+ {
+ System.out.println("Sending for up to " + (duration / 1000000000f) + " seconds.");
+ }
+
+ if (_rate > 0)
+ {
+ System.out.println("Sending at " + _rate + " messages per second.");
+ }
+
+ if (numMessages > 0)
+ {
+ System.out.println("Sending up to " + numMessages + " messages.");
+ }
+
+ // Establish the connection and the message producer.
+ establishConnection(true, false);
+ _connection.start();
+
+ Message message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent);
+
+ // Send pings until a terminating condition is received.
+ boolean endCondition = false;
+ int messagesSent = 0;
+ int messagesCommitted = 0;
+ int messagesNotCommitted = 0;
+ long start = System.nanoTime();
+
+ // Clear console in.
+ clearConsole();
+
+ while (!endCondition)
+ {
+ boolean committed = false;
+
+ try
+ {
+ committed = sendMessage(messagesSent, message) && _transacted;
+
+ messagesSent++;
+ messagesNotCommitted++;
+
+ // Keep count of the number of messsages currently committed and pending commit.
+ if (committed)
+ {
+ log.debug("Adding " + messagesNotCommitted + " messages to the committed count.");
+ messagesCommitted += messagesNotCommitted;
+ messagesNotCommitted = 0;
+
+ System.out.println("Commited: " + messagesCommitted);
+ }
+ }
+ catch (JMSException e)
+ {
+ log.debug("Got JMSException whilst sending.");
+ _publish = false;
+ }
+
+ // Perform the arbitrary action if the number of messages sent has reached the right number.
+ if (messagesSent == numMessagesToAction)
+ {
+ System.out.println("At action point, Messages sent = " + messagesSent + ", Messages Committed = "
+ + messagesCommitted + ", Messages not Committed = " + messagesNotCommitted);
+ takeAction();
+ }
+
+ // Determine if the end condition has been met, based on the number of messages, time passed, errors on
+ // the connection or user input.
+ long now = System.nanoTime();
+
+ if ((duration != 0) && ((now - start) > duration))
+ {
+ System.out.println("Send halted because duration expired.");
+ endCondition = true;
+ }
+ else if ((numMessages != 0) && (messagesSent >= numMessages))
+ {
+ System.out.println("Send halted because # messages completed.");
+ endCondition = true;
+ }
+ else if (System.in.available() > 0)
+ {
+ System.out.println("Send halted by user input.");
+ endCondition = true;
+
+ clearConsole();
+ }
+ else if (!_publish)
+ {
+ System.out.println("Send halted by error on the connection.");
+ endCondition = true;
+ }
+ }
+
+ log.debug("messagesSent = " + messagesSent);
+ log.debug("messagesCommitted = " + messagesCommitted);
+ log.debug("messagesNotCommitted = " + messagesNotCommitted);
+
+ System.out.println("Messages sent: " + messagesSent + ", Messages Committed = " + messagesCommitted
+ + ", Messages not Committed = " + messagesNotCommitted);
+
+ return messagesSent;
+ }
+
+ protected void closeConnection()
+ {
+ // Clean up the connection.
+ try
+ {
+ close();
+ }
+ catch (JMSException e)
+ {
+ log.debug("There was an error whilst closing the connection: " + e, e);
+ System.out.println("There was an error whilst closing the connection.");
+
+ // Ignore as did best could manage to clean up.
+ }
+ }
+
+ protected void receive(int messagesSent) throws Exception
+ {
+ // Re-establish the connection and the message consumer.
+ _queueJVMSequenceID = new AtomicInteger();
+ _queueSharedID = new AtomicInteger();
+
+ establishConnection(false, true);
+ _consumer[0].setMessageListener(null);
+ _consumerConnection[0].start();
+
+ // Try to receive all of the pings that were successfully sent.
+ int messagesReceived = 0;
+ boolean endCondition = false;
+
+ while (!endCondition)
+ {
+ // Message received = _consumer.receiveNoWait();
+ Message received = _consumer[0].receive(TIME_OUT);
+ log.debug("received = " + received);
+
+ if (received != null)
+ {
+ messagesReceived++;
+ }
+
+ // Determine if the end condition has been met, based on the number of messages and time passed since last
+ // receiving a message.
+ if (received == null)
+ {
+ System.out.println("Timed out.");
+ endCondition = true;
+ }
+ else if (messagesReceived >= messagesSent)
+ {
+ System.out.println("Got all messages.");
+ endCondition = true;
+ }
+ }
+
+ // Ensure messages received are committed.
+ if (_consTransacted)
+ {
+ try
+ {
+ _consumerSession[0].commit();
+ System.out.println("Committed for all messages received.");
+ }
+ catch (JMSException e)
+ {
+ log.debug("Error during commit: " + e, e);
+ System.out.println("Error during commit.");
+ try
+ {
+ _consumerSession[0].rollback();
+ System.out.println("Rolled back on all messages received.");
+ }
+ catch (JMSException e2)
+ {
+ log.debug("Error during rollback: " + e, e);
+ System.out.println("Error on roll back of all messages received.");
+ }
+
+ }
+ }
+
+ log.debug("messagesReceived = " + messagesReceived);
+
+ System.out.println("Messages received: " + messagesReceived);
+
+ // Clean up the connection.
+ close();
+ }
+
+ /**
+ * Clears any pending input from the console.
+ */
+ private void clearConsole()
+ {
+ try
+ {
+ BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
+
+ // System.in.skip(System.in.available());
+ while (bis.ready())
+ {
+ bis.readLine();
+ }
+ }
+ catch (IOException e)
+ { }
+ }
+
+ /**
+ * Returns the ping destinations themselves as the reply destinations for this pinger to listen to. This has the
+ * effect of making this pinger listen to its own pings.
+ *
+ * @return The ping destinations.
+ */
+ public List<Destination> getReplyDestinations()
+ {
+ return _pingDestinations;
+ }
+
+ /**
+ * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered with
+ * the runtime system as a shutdown hook. This shutdown hook sets an additional terminate flag, compared with the
+ * shutdown hook in {@link PingPongProducer}, because the publish flag is used to indicate that sending or receiving
+ * message should stop, not that the application should termiante.
+ *
+ * @return A shutdown hook for the ping loop.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ stop();
+ terminate = true;
+ }
+ });
+ }
+
+ /**
+ * Performs an aribtrary action once the 'numMesagesToAction' count is reached on sending messages. This default
+ * implementation does nothing.
+ */
+ public void takeAction()
+ { }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java
index 215dbcefa3..5ba4004c56 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingLatencyTestPerf.java
@@ -1,311 +1,311 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.ping;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.requestreply.PingPongProducer;
-
-import org.apache.qpid.junit.extensions.TimingController;
-import org.apache.qpid.junit.extensions.TimingControllerAware;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.JMSException;
-import javax.jms.Message;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * PingLatencyTestPerf is a performance test that outputs multiple timings from its test method, using the timing
- * controller interface supplied by the test runner from a seperate listener thread. It outputs round trip timings for
- * individual ping messages rather than for how long a complete batch of messages took to process. It also differs from
- * the {@link PingTestPerf} test that it extends because it can output timings as replies are received, rather than
- * waiting until all expected replies are received.
- *
- * <p/>This test does not output timings for every single ping message, as when running at high volume, writing the test
- * log for a vast number of messages would slow the testing down. Instead samples ping latency occasionally. The
- * frequency of ping sampling is set using the {@link #TEST_RESULTS_BATCH_SIZE_PROPNAME} property, to override the
- * default of every {@link #DEFAULT_TEST_RESULTS_BATCH_SIZE}.
- *
- * <p/>The size parameter logged for each individual ping is set to the size of the batch of messages that the
- * individual timed ping was taken from, rather than 1 for a single message. This is so that the total throughput
- * (messages / time) can be calculated in order to examine the relationship between throughput and latency.
- *
- * <p/><table id="crc"><caption>CRC Card</caption> <tr><td> Responsibilities <th> Collaborations <tr><td> Send many ping
- * messages and output timings for sampled individual pings. </table>
- */
-public class PingLatencyTestPerf extends PingTestPerf implements TimingControllerAware
-{
- private static Logger _logger = Logger.getLogger(PingLatencyTestPerf.class);
-
- /** Holds the name of the property to get the test results logging batch size. */
- public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "batchSize";
-
- /** Holds the default test results logging batch size. */
- public static final int DEFAULT_TEST_RESULTS_BATCH_SIZE = 1000;
-
- /** Used to hold the timing controller passed from the test runner. */
- private TimingController _timingController;
-
- /** Used to generate unique correlation ids for each test run. */
- private AtomicLong corellationIdGenerator = new AtomicLong();
-
- /**
- * Holds test specifics by correlation id. This consists of the expected number of messages and the timing
- * controler.
- */
- private Map<String, PerCorrelationId> perCorrelationIds =
- Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
-
- /** Holds the batched results listener, that does logging on batch boundaries. */
- private BatchedResultsListener batchedResultsListener = null;
-
- /**
- * Creates a new asynchronous ping performance test with the specified name.
- *
- * @param name The test name.
- */
- public PingLatencyTestPerf(String name)
- {
- super(name);
-
- // Sets up the test parameters with defaults.
- ParsedProperties.setSysPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME,
- Integer.toString(DEFAULT_TEST_RESULTS_BATCH_SIZE));
- }
-
- /** Compile all the tests into a test suite. */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("Ping Latency Tests");
-
- // Run performance tests in read committed mode.
- suite.addTest(new PingLatencyTestPerf("testPingLatency"));
-
- return suite;
- }
-
- /**
- * Accepts a timing controller from the test runner.
- *
- * @param timingController The timing controller to register mutliple timings with.
- */
- public void setTimingController(TimingController timingController)
- {
- _timingController = timingController;
- }
-
- /**
- * Gets the timing controller passed in by the test runner.
- *
- * @return The timing controller passed in by the test runner.
- */
- public TimingController getTimingController()
- {
- return _timingController;
- }
-
- /**
- * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until all
- * replies have been received or a time out occurs before exiting this method.
- *
- * @param numPings The number of pings to send.
- */
- public void testPingLatency(int numPings) throws Exception
- {
- _logger.debug("public void testPingLatency(int numPings): called");
-
- // Ensure that at least one ping was requeusted.
- if (numPings == 0)
- {
- _logger.error("Number of pings requested was zero.");
- }
-
- // Get the per thread test setup to run the test through.
- PerThreadSetup perThreadSetup = threadSetup.get();
- PingClient pingClient = perThreadSetup._pingClient;
-
- // Advance the correlation id of messages to send, to make it unique for this run.
- String messageCorrelationId = Long.toString(corellationIdGenerator.incrementAndGet());
- _logger.debug("messageCorrelationId = " + messageCorrelationId);
-
- // Initialize the count and timing controller for the new correlation id.
- PerCorrelationId perCorrelationId = new PerCorrelationId();
- TimingController tc = getTimingController().getControllerForCurrentThread();
- perCorrelationId._tc = tc;
- perCorrelationId._expectedCount = numPings;
- perCorrelationIds.put(messageCorrelationId, perCorrelationId);
-
- // Attach the chained message listener to the ping producer to listen asynchronously for the replies to these
- // messages.
- pingClient.setChainedMessageListener(batchedResultsListener);
-
- // Generate a sample message of the specified size.
- Message msg =
- pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
- testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
- testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
-
- // Send the requested number of messages, and wait until they have all been received.
- long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
- int numReplies = pingClient.pingAndWaitForReply(msg, numPings, timeout, null);
-
- // Check that all the replies were received and log a fail if they were not.
- if (numReplies < numPings)
- {
- tc.completeTest(false, 0);
- }
-
- // Remove the chained message listener from the ping producer.
- pingClient.removeChainedMessageListener();
-
- // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up.
- perCorrelationIds.remove(messageCorrelationId);
- }
-
- /** Performs test fixture creation on a per thread basis. This will only be called once for each test thread. */
- public void threadSetUp()
- {
- _logger.debug("public void threadSetUp(): called");
-
- try
- {
- // Call the set up method in the super class. This creates a PingClient pinger.
- super.threadSetUp();
-
- // Create the chained message listener, only if it has not already been created. This is set up with the
- // batch size property, to tell it what batch size to output results on. A synchronized block is used to
- // ensure that only one thread creates this.
- synchronized (this)
- {
- if (batchedResultsListener == null)
- {
- int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME));
- batchedResultsListener = new BatchedResultsListener(batchSize);
- }
- }
-
- // Get the set up that the super class created.
- PerThreadSetup perThreadSetup = threadSetup.get();
-
- // Register the chained message listener on the pinger to do its asynchronous test timings from.
- perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener);
- }
- catch (Exception e)
- {
- _logger.warn("There was an exception during per thread setup.", e);
- }
- }
-
- /**
- * BatchedResultsListener is a {@link org.apache.qpid.requestreply.PingPongProducer.ChainedMessageListener} that can
- * be attached to the pinger, in order to receive notifications about every message received and the number
- * remaining to be received. Whenever the number remaining crosses a batch size boundary this results listener
- * outputs a test timing for the actual number of messages received in the current batch.
- */
- private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener
- {
- /** The test results logging batch size. */
- int _batchSize;
- private boolean _strictAMQP;
-
- /**
- * Creates a results listener on the specified batch size.
- *
- * @param batchSize The batch size to use.
- */
- public BatchedResultsListener(int batchSize)
- {
- _batchSize = batchSize;
- _strictAMQP =
- Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP,
- AMQSession.STRICT_AMQP_DEFAULT));
- }
-
- /**
- * This callback method is called from all of the pingers that this test creates. It uses the correlation id
- * from the message to identify the timing controller for the test thread that was responsible for sending those
- * messages.
- *
- * @param message The message.
- * @param remainingCount The count of messages remaining to be received with a particular correlation id.
- *
- * @throws javax.jms.JMSException Any underlying JMSException is allowed to fall through.
- */
- public void onMessage(Message message, int remainingCount, long latency) throws JMSException
- {
- _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount + "): called");
-
- // Check if a batch boundary has been crossed.
- if ((remainingCount % _batchSize) == 0)
- {
- // Extract the correlation id from the message.
- String correlationId = message.getJMSCorrelationID();
-
- // Get the details for the correlation id and check that they are not null. They can become null
- // if a test times out.
- PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId);
- if (perCorrelationId != null)
- {
- // Get the timing controller and expected count for this correlation id.
- TimingController tc = perCorrelationId._tc;
- int expected = perCorrelationId._expectedCount;
-
- // Calculate how many messages were actually received in the last batch. This will be the batch size
- // except where the number expected is not a multiple of the batch size and this is the first remaining
- // count to cross a batch size boundary, in which case it will be the number expected modulo the batch
- // size.
- int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize;
-
- // Register a test result for the correlation id.
- try
- {
- tc.completeTest(true, receivedInBatch, latency);
- }
- catch (InterruptedException e)
- {
- // Ignore this. It means the test runner wants to stop as soon as possible.
- _logger.warn("Got InterruptedException.", e);
- }
- }
- // Else ignore, test timed out. Should log a fail here?
- }
- }
- }
-
- /**
- * Holds state specific to each correlation id, needed to output test results. This consists of the count of the
- * total expected number of messages, and the timing controller for the thread sending those message ids.
- */
- private static class PerCorrelationId
- {
- public int _expectedCount;
- public TimingController _tc;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.ping;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.requestreply.PingPongProducer;
+
+import org.apache.qpid.junit.extensions.TimingController;
+import org.apache.qpid.junit.extensions.TimingControllerAware;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * PingLatencyTestPerf is a performance test that outputs multiple timings from its test method, using the timing
+ * controller interface supplied by the test runner from a seperate listener thread. It outputs round trip timings for
+ * individual ping messages rather than for how long a complete batch of messages took to process. It also differs from
+ * the {@link PingTestPerf} test that it extends because it can output timings as replies are received, rather than
+ * waiting until all expected replies are received.
+ *
+ * <p/>This test does not output timings for every single ping message, as when running at high volume, writing the test
+ * log for a vast number of messages would slow the testing down. Instead samples ping latency occasionally. The
+ * frequency of ping sampling is set using the {@link #TEST_RESULTS_BATCH_SIZE_PROPNAME} property, to override the
+ * default of every {@link #DEFAULT_TEST_RESULTS_BATCH_SIZE}.
+ *
+ * <p/>The size parameter logged for each individual ping is set to the size of the batch of messages that the
+ * individual timed ping was taken from, rather than 1 for a single message. This is so that the total throughput
+ * (messages / time) can be calculated in order to examine the relationship between throughput and latency.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption> <tr><td> Responsibilities <th> Collaborations <tr><td> Send many ping
+ * messages and output timings for sampled individual pings. </table>
+ */
+public class PingLatencyTestPerf extends PingTestPerf implements TimingControllerAware
+{
+ private static Logger _logger = Logger.getLogger(PingLatencyTestPerf.class);
+
+ /** Holds the name of the property to get the test results logging batch size. */
+ public static final String TEST_RESULTS_BATCH_SIZE_PROPNAME = "batchSize";
+
+ /** Holds the default test results logging batch size. */
+ public static final int DEFAULT_TEST_RESULTS_BATCH_SIZE = 1000;
+
+ /** Used to hold the timing controller passed from the test runner. */
+ private TimingController _timingController;
+
+ /** Used to generate unique correlation ids for each test run. */
+ private AtomicLong corellationIdGenerator = new AtomicLong();
+
+ /**
+ * Holds test specifics by correlation id. This consists of the expected number of messages and the timing
+ * controler.
+ */
+ private Map<String, PerCorrelationId> perCorrelationIds =
+ Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
+
+ /** Holds the batched results listener, that does logging on batch boundaries. */
+ private BatchedResultsListener batchedResultsListener = null;
+
+ /**
+ * Creates a new asynchronous ping performance test with the specified name.
+ *
+ * @param name The test name.
+ */
+ public PingLatencyTestPerf(String name)
+ {
+ super(name);
+
+ // Sets up the test parameters with defaults.
+ ParsedProperties.setSysPropertyIfNull(TEST_RESULTS_BATCH_SIZE_PROPNAME,
+ Integer.toString(DEFAULT_TEST_RESULTS_BATCH_SIZE));
+ }
+
+ /** Compile all the tests into a test suite. */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Ping Latency Tests");
+
+ // Run performance tests in read committed mode.
+ suite.addTest(new PingLatencyTestPerf("testPingLatency"));
+
+ return suite;
+ }
+
+ /**
+ * Accepts a timing controller from the test runner.
+ *
+ * @param timingController The timing controller to register mutliple timings with.
+ */
+ public void setTimingController(TimingController timingController)
+ {
+ _timingController = timingController;
+ }
+
+ /**
+ * Gets the timing controller passed in by the test runner.
+ *
+ * @return The timing controller passed in by the test runner.
+ */
+ public TimingController getTimingController()
+ {
+ return _timingController;
+ }
+
+ /**
+ * Sends the specified number of pings, asynchronously outputs timings on every batch boundary, and waits until all
+ * replies have been received or a time out occurs before exiting this method.
+ *
+ * @param numPings The number of pings to send.
+ */
+ public void testPingLatency(int numPings) throws Exception
+ {
+ _logger.debug("public void testPingLatency(int numPings): called");
+
+ // Ensure that at least one ping was requeusted.
+ if (numPings == 0)
+ {
+ _logger.error("Number of pings requested was zero.");
+ }
+
+ // Get the per thread test setup to run the test through.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+ PingClient pingClient = perThreadSetup._pingClient;
+
+ // Advance the correlation id of messages to send, to make it unique for this run.
+ String messageCorrelationId = Long.toString(corellationIdGenerator.incrementAndGet());
+ _logger.debug("messageCorrelationId = " + messageCorrelationId);
+
+ // Initialize the count and timing controller for the new correlation id.
+ PerCorrelationId perCorrelationId = new PerCorrelationId();
+ TimingController tc = getTimingController().getControllerForCurrentThread();
+ perCorrelationId._tc = tc;
+ perCorrelationId._expectedCount = numPings;
+ perCorrelationIds.put(messageCorrelationId, perCorrelationId);
+
+ // Attach the chained message listener to the ping producer to listen asynchronously for the replies to these
+ // messages.
+ pingClient.setChainedMessageListener(batchedResultsListener);
+
+ // Generate a sample message of the specified size.
+ Message msg =
+ pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
+
+ // Send the requested number of messages, and wait until they have all been received.
+ long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
+ int numReplies = pingClient.pingAndWaitForReply(msg, numPings, timeout, null);
+
+ // Check that all the replies were received and log a fail if they were not.
+ if (numReplies < numPings)
+ {
+ tc.completeTest(false, 0);
+ }
+
+ // Remove the chained message listener from the ping producer.
+ pingClient.removeChainedMessageListener();
+
+ // Remove the expected count and timing controller for the message correlation id, to ensure they are cleaned up.
+ perCorrelationIds.remove(messageCorrelationId);
+ }
+
+ /** Performs test fixture creation on a per thread basis. This will only be called once for each test thread. */
+ public void threadSetUp()
+ {
+ _logger.debug("public void threadSetUp(): called");
+
+ try
+ {
+ // Call the set up method in the super class. This creates a PingClient pinger.
+ super.threadSetUp();
+
+ // Create the chained message listener, only if it has not already been created. This is set up with the
+ // batch size property, to tell it what batch size to output results on. A synchronized block is used to
+ // ensure that only one thread creates this.
+ synchronized (this)
+ {
+ if (batchedResultsListener == null)
+ {
+ int batchSize = Integer.parseInt(testParameters.getProperty(TEST_RESULTS_BATCH_SIZE_PROPNAME));
+ batchedResultsListener = new BatchedResultsListener(batchSize);
+ }
+ }
+
+ // Get the set up that the super class created.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Register the chained message listener on the pinger to do its asynchronous test timings from.
+ perThreadSetup._pingClient.setChainedMessageListener(batchedResultsListener);
+ }
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
+ }
+
+ /**
+ * BatchedResultsListener is a {@link org.apache.qpid.requestreply.PingPongProducer.ChainedMessageListener} that can
+ * be attached to the pinger, in order to receive notifications about every message received and the number
+ * remaining to be received. Whenever the number remaining crosses a batch size boundary this results listener
+ * outputs a test timing for the actual number of messages received in the current batch.
+ */
+ private class BatchedResultsListener implements PingPongProducer.ChainedMessageListener
+ {
+ /** The test results logging batch size. */
+ int _batchSize;
+ private boolean _strictAMQP;
+
+ /**
+ * Creates a results listener on the specified batch size.
+ *
+ * @param batchSize The batch size to use.
+ */
+ public BatchedResultsListener(int batchSize)
+ {
+ _batchSize = batchSize;
+ _strictAMQP =
+ Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP,
+ AMQSession.STRICT_AMQP_DEFAULT));
+ }
+
+ /**
+ * This callback method is called from all of the pingers that this test creates. It uses the correlation id
+ * from the message to identify the timing controller for the test thread that was responsible for sending those
+ * messages.
+ *
+ * @param message The message.
+ * @param remainingCount The count of messages remaining to be received with a particular correlation id.
+ *
+ * @throws javax.jms.JMSException Any underlying JMSException is allowed to fall through.
+ */
+ public void onMessage(Message message, int remainingCount, long latency) throws JMSException
+ {
+ _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount + "): called");
+
+ // Check if a batch boundary has been crossed.
+ if ((remainingCount % _batchSize) == 0)
+ {
+ // Extract the correlation id from the message.
+ String correlationId = message.getJMSCorrelationID();
+
+ // Get the details for the correlation id and check that they are not null. They can become null
+ // if a test times out.
+ PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationId);
+ if (perCorrelationId != null)
+ {
+ // Get the timing controller and expected count for this correlation id.
+ TimingController tc = perCorrelationId._tc;
+ int expected = perCorrelationId._expectedCount;
+
+ // Calculate how many messages were actually received in the last batch. This will be the batch size
+ // except where the number expected is not a multiple of the batch size and this is the first remaining
+ // count to cross a batch size boundary, in which case it will be the number expected modulo the batch
+ // size.
+ int receivedInBatch = ((expected - remainingCount) < _batchSize) ? (expected % _batchSize) : _batchSize;
+
+ // Register a test result for the correlation id.
+ try
+ {
+ tc.completeTest(true, receivedInBatch, latency);
+ }
+ catch (InterruptedException e)
+ {
+ // Ignore this. It means the test runner wants to stop as soon as possible.
+ _logger.warn("Got InterruptedException.", e);
+ }
+ }
+ // Else ignore, test timed out. Should log a fail here?
+ }
+ }
+ }
+
+ /**
+ * Holds state specific to each correlation id, needed to output test results. This consists of the count of the
+ * total expected number of messages, and the timing controller for the thread sending those message ids.
+ */
+ private static class PerCorrelationId
+ {
+ public int _expectedCount;
+ public TimingController _tc;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
index 2879f0c322..04e723069a 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
@@ -1,93 +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.ping;
-
-import java.util.Properties;
-
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.ObjectMessage;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.message.TestMessageFactory;
-import org.apache.qpid.util.CommandLineParser;
-
-/**
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-public class PingSendOnlyClient extends PingDurableClient
-{
- private static final Logger log = Logger.getLogger(PingSendOnlyClient.class);
-
- public PingSendOnlyClient(Properties overrides) throws Exception
- {
- super(overrides);
- }
-
- /**
- * Starts the ping/wait/receive process.
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- try
- {
- // Create a ping producer overriding its defaults with all options passed on the command line.
- Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
- PingSendOnlyClient pingProducer = new PingSendOnlyClient(options);
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
-
- // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
- // pingProducer.getConnection().setExceptionListener(pingProducer);
-
- // Run the test procedure.
- int sent = pingProducer.send();
- pingProducer.waitForUser("Press return to close connection and quit.");
- pingProducer.closeConnection();
-
- System.exit(0);
- }
- catch (Exception e)
- {
- System.err.println(e.getMessage());
- log.error("Top level handler caught execption.", e);
- System.exit(1);
- }
- }
-
- public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
- {
- Message msg = TestMessageFactory.newTextMessage(_producerSession, messageSize);
-
- // Timestamp the message in nanoseconds.
- msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
-
- return msg;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.ping;
+
+import java.util.Properties;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.message.TestMessageFactory;
+import org.apache.qpid.util.CommandLineParser;
+
+/**
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ */
+public class PingSendOnlyClient extends PingDurableClient
+{
+ private static final Logger log = Logger.getLogger(PingSendOnlyClient.class);
+
+ public PingSendOnlyClient(Properties overrides) throws Exception
+ {
+ super(overrides);
+ }
+
+ /**
+ * Starts the ping/wait/receive process.
+ *
+ * @param args The command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ // Create a ping producer overriding its defaults with all options passed on the command line.
+ Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
+ PingSendOnlyClient pingProducer = new PingSendOnlyClient(options);
+
+ // Create a shutdown hook to terminate the ping-pong producer.
+ Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
+
+ // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
+ // pingProducer.getConnection().setExceptionListener(pingProducer);
+
+ // Run the test procedure.
+ int sent = pingProducer.send();
+ pingProducer.waitForUser("Press return to close connection and quit.");
+ pingProducer.closeConnection();
+
+ System.exit(0);
+ }
+ catch (Exception e)
+ {
+ System.err.println(e.getMessage());
+ log.error("Top level handler caught execption.", e);
+ System.exit(1);
+ }
+ }
+
+ public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
+ {
+ Message msg = TestMessageFactory.newTextMessage(_producerSession, messageSize);
+
+ // Timestamp the message in nanoseconds.
+ msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
+
+ return msg;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java
index fb071a87fe..94b8ea662e 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingTestPerf.java
@@ -1,196 +1,196 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.ping;
-
-import junit.framework.Assert;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.requestreply.PingPongProducer;
-
-import org.apache.qpid.junit.extensions.AsymptoticTestCase;
-import org.apache.qpid.junit.extensions.TestThreadAware;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import javax.jms.*;
-
-/**
- * PingTestPerf is a ping test, that has been written with the intention of being scaled up to run many times
- * simultaneously to simluate many clients/producers/connections.
- *
- * <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of a single
- * full round trip ping. This test may be scaled up using a suitable JUnit test runner.
- *
- * <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
- * temporary queue for replies. This setup is only established once for all the test repeats/threads that may be run,
- * except if the connection is lost in which case an attempt to re-establish the setup is made.
- *
- * <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
- * is the name of the temporary queue, fires off a message on the original queue and waits for a response on the
- * temporary queue.
- *
- * <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-public class PingTestPerf extends AsymptoticTestCase implements TestThreadAware
-{
- private static Logger _logger = Logger.getLogger(PingTestPerf.class);
-
- /** Thread local to hold the per-thread test setup fields. */
- ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
-
- /** Holds a property reader to extract the test parameters from. */
- protected ParsedProperties testParameters =
- TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/);
-
- public PingTestPerf(String name)
- {
- super(name);
-
- _logger.debug("testParameters = " + testParameters);
- }
-
- /**
- * Compile all the tests into a test suite.
- * @return The test method testPingOk.
- */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("Ping Performance Tests");
-
- // Run performance tests in read committed mode.
- suite.addTest(new PingTestPerf("testPingOk"));
-
- return suite;
- }
-
- public void testPingOk(int numPings) throws Exception
- {
- if (numPings == 0)
- {
- Assert.fail("Number of pings requested was zero.");
- }
-
- // Get the per thread test setup to run the test through.
- PerThreadSetup perThreadSetup = threadSetup.get();
-
- if (perThreadSetup == null)
- {
- Assert.fail("Could not get per thread test setup, it was null.");
- }
-
- // Generate a sample message. This message is already time stamped and has its reply-to destination set.
- Message msg =
- perThreadSetup._pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
- testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
- testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
-
- // start the test
- long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
- int numReplies = perThreadSetup._pingClient.pingAndWaitForReply(msg, numPings, timeout, null);
-
- // Fail the test if the timeout was exceeded.
- if (numReplies != perThreadSetup._pingClient.getExpectedNumPings(numPings))
- {
- Assert.fail("The ping timed out after " + timeout + " ms. Messages Sent = " + numPings + ", MessagesReceived = "
- + numReplies);
- }
- }
-
- /**
- * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
- */
- public void threadSetUp()
- {
- _logger.debug("public void threadSetUp(): called");
-
- try
- {
- PerThreadSetup perThreadSetup = new PerThreadSetup();
-
- // This is synchronized because there is a race condition, which causes one connection to sleep if
- // all threads try to create connection concurrently.
- synchronized (this)
- {
- // Establish a client to ping a Destination and listen the reply back from same Destination
- perThreadSetup._pingClient = new PingClient(testParameters);
- perThreadSetup._pingClient.establishConnection(true, true);
- }
- // Start the client connection
- perThreadSetup._pingClient.start();
-
- // Attach the per-thread set to the thread.
- threadSetup.set(perThreadSetup);
- }
- catch (Exception e)
- {
- _logger.warn("There was an exception during per thread setup.", e);
- }
- }
-
- /**
- * Performs test fixture clean
- */
- public void threadTearDown()
- {
- _logger.debug("public void threadTearDown(): called");
-
- try
- {
- // Get the per thread test fixture.
- PerThreadSetup perThreadSetup = threadSetup.get();
-
- // Close the pingers so that it cleans up its connection cleanly.
- synchronized (this)
- {
- if ((perThreadSetup != null) && (perThreadSetup._pingClient != null))
- {
- perThreadSetup._pingClient.close();
- }
- }
- }
- catch (JMSException e)
- {
- _logger.warn("There was an exception during per thread tear down.");
- }
- finally
- {
- // Ensure the per thread fixture is reclaimed.
- threadSetup.remove();
- }
- }
-
- protected static class PerThreadSetup
- {
- /**
- * Holds the test ping client.
- */
- protected PingClient _pingClient;
- protected String _correlationId;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.ping;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.requestreply.PingPongProducer;
+
+import org.apache.qpid.junit.extensions.AsymptoticTestCase;
+import org.apache.qpid.junit.extensions.TestThreadAware;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import javax.jms.*;
+
+/**
+ * PingTestPerf is a ping test, that has been written with the intention of being scaled up to run many times
+ * simultaneously to simluate many clients/producers/connections.
+ *
+ * <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of a single
+ * full round trip ping. This test may be scaled up using a suitable JUnit test runner.
+ *
+ * <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
+ * temporary queue for replies. This setup is only established once for all the test repeats/threads that may be run,
+ * except if the connection is lost in which case an attempt to re-establish the setup is made.
+ *
+ * <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
+ * is the name of the temporary queue, fires off a message on the original queue and waits for a response on the
+ * temporary queue.
+ *
+ * <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ */
+public class PingTestPerf extends AsymptoticTestCase implements TestThreadAware
+{
+ private static Logger _logger = Logger.getLogger(PingTestPerf.class);
+
+ /** Thread local to hold the per-thread test setup fields. */
+ ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
+
+ /** Holds a property reader to extract the test parameters from. */
+ protected ParsedProperties testParameters =
+ TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/);
+
+ public PingTestPerf(String name)
+ {
+ super(name);
+
+ _logger.debug("testParameters = " + testParameters);
+ }
+
+ /**
+ * Compile all the tests into a test suite.
+ * @return The test method testPingOk.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Ping Performance Tests");
+
+ // Run performance tests in read committed mode.
+ suite.addTest(new PingTestPerf("testPingOk"));
+
+ return suite;
+ }
+
+ public void testPingOk(int numPings) throws Exception
+ {
+ if (numPings == 0)
+ {
+ Assert.fail("Number of pings requested was zero.");
+ }
+
+ // Get the per thread test setup to run the test through.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ if (perThreadSetup == null)
+ {
+ Assert.fail("Could not get per thread test setup, it was null.");
+ }
+
+ // Generate a sample message. This message is already time stamped and has its reply-to destination set.
+ Message msg =
+ perThreadSetup._pingClient.getTestMessage(perThreadSetup._pingClient.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
+
+ // start the test
+ long timeout = Long.parseLong(testParameters.getProperty(PingPongProducer.TIMEOUT_PROPNAME));
+ int numReplies = perThreadSetup._pingClient.pingAndWaitForReply(msg, numPings, timeout, null);
+
+ // Fail the test if the timeout was exceeded.
+ if (numReplies != perThreadSetup._pingClient.getExpectedNumPings(numPings))
+ {
+ Assert.fail("The ping timed out after " + timeout + " ms. Messages Sent = " + numPings + ", MessagesReceived = "
+ + numReplies);
+ }
+ }
+
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ _logger.debug("public void threadSetUp(): called");
+
+ try
+ {
+ PerThreadSetup perThreadSetup = new PerThreadSetup();
+
+ // This is synchronized because there is a race condition, which causes one connection to sleep if
+ // all threads try to create connection concurrently.
+ synchronized (this)
+ {
+ // Establish a client to ping a Destination and listen the reply back from same Destination
+ perThreadSetup._pingClient = new PingClient(testParameters);
+ perThreadSetup._pingClient.establishConnection(true, true);
+ }
+ // Start the client connection
+ perThreadSetup._pingClient.start();
+
+ // Attach the per-thread set to the thread.
+ threadSetup.set(perThreadSetup);
+ }
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
+ }
+
+ /**
+ * Performs test fixture clean
+ */
+ public void threadTearDown()
+ {
+ _logger.debug("public void threadTearDown(): called");
+
+ try
+ {
+ // Get the per thread test fixture.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Close the pingers so that it cleans up its connection cleanly.
+ synchronized (this)
+ {
+ if ((perThreadSetup != null) && (perThreadSetup._pingClient != null))
+ {
+ perThreadSetup._pingClient.close();
+ }
+ }
+ }
+ catch (JMSException e)
+ {
+ _logger.warn("There was an exception during per thread tear down.");
+ }
+ finally
+ {
+ // Ensure the per thread fixture is reclaimed.
+ threadSetup.remove();
+ }
+ }
+
+ protected static class PerThreadSetup
+ {
+ /**
+ * Holds the test ping client.
+ */
+ protected PingClient _pingClient;
+ protected String _correlationId;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
index 0712557383..8e010ccf07 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongBouncer.java
@@ -1,453 +1,453 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.requestreply;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import javax.jms.*;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.jms.ConnectionListener;
-import org.apache.qpid.jms.Session;
-import org.apache.qpid.topic.Config;
-import org.apache.qpid.exchange.ExchangeDefaults;
-
-/**
- * PingPongBouncer is a message listener the bounces back messages to their reply to destination. This is used to return
- * ping messages generated by {@link org.apache.qpid.requestreply.PingPongProducer} but could be used for other purposes
- * too.
- *
- * <p/>The correlation id from the received message is extracted, and placed into the reply as the correlation id. Messages
- * are bounced back to their reply-to destination. The original sender of the message has the option to use either a unique
- * temporary queue or the correlation id to correlate the original message to the reply.
- *
- * <p/>There is a verbose mode flag which causes information about each ping to be output to the console
- * (info level logging, so usually console). This can be helpfull to check the bounce backs are happening but should
- * be disabled for real timing tests as writing to the console will slow things down.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Bounce back messages to their reply to destination.
- * <tr><td> Provide command line invocation to start the bounce back on a configurable broker url.
- * </table>
- *
- * @todo Replace the command line parsing with a neater tool.
- *
- * @todo Make verbose accept a number of messages, only prints to console every X messages.
- */
-public class PingPongBouncer implements MessageListener
-{
- private static final Logger _logger = Logger.getLogger(PingPongBouncer.class);
-
- /** The default prefetch size for the message consumer. */
- private static final int PREFETCH = 1;
-
- /** The default no local flag for the message consumer. */
- private static final boolean NO_LOCAL = true;
-
- private static final String DEFAULT_DESTINATION_NAME = "ping";
-
- /** The default exclusive flag for the message consumer. */
- private static final boolean EXCLUSIVE = false;
-
- /** A convenient formatter to use when time stamping output. */
- protected static final SimpleDateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
-
- /** Used to indicate that the reply generator should log timing info to the console (logger info level). */
- private boolean _verbose = false;
-
- /** Determines whether this bounce back client bounces back messages persistently. */
- private boolean _persistent = false;
-
- private Destination _consumerDestination;
-
- /** Keeps track of the response destination of the previous message for the last reply to producer cache. */
- private Destination _lastResponseDest;
-
- /** The producer for sending replies with. */
- private MessageProducer _replyProducer;
-
- /** The consumer controlSession. */
- private Session _consumerSession;
-
- /** The producer controlSession. */
- private Session _producerSession;
-
- /** Holds the connection to the broker. */
- private AMQConnection _connection;
-
- /** Flag used to indicate if this is a point to point or pub/sub ping client. */
- private boolean _isPubSub = false;
-
- /**
- * This flag is used to indicate that the user should be prompted to kill a broker, in order to test
- * failover, immediately before committing a transaction.
- */
- protected boolean _failBeforeCommit = false;
-
- /**
- * This flag is used to indicate that the user should be prompted to a kill a broker, in order to test
- * failover, immediate after committing a transaction.
- */
- protected boolean _failAfterCommit = false;
-
- /**
- * Creates a PingPongBouncer on the specified producer and consumer sessions.
- *
- * @param brokerDetails The addresses of the brokers to connect to.
- * @param username The broker username.
- * @param password The broker password.
- * @param virtualpath The virtual host name within the broker.
- * @param destinationName The name of the queue to receive pings on
- * (or root of the queue name where many queues are generated).
- * @param persistent A flag to indicate that persistent message should be used.
- * @param transacted A flag to indicate that pings should be sent within transactions.
- * @param selector A message selector to filter received pings with.
- * @param verbose A flag to indicate that message timings should be sent to the console.
- *
- * @throws Exception All underlying exceptions allowed to fall through. This is only test code...
- */
- public PingPongBouncer(String brokerDetails, String username, String password, String virtualpath,
- String destinationName, boolean persistent, boolean transacted, String selector, boolean verbose,
- boolean pubsub) throws Exception
- {
- // Create a client id to uniquely identify this client.
- InetAddress address = InetAddress.getLocalHost();
- String clientId = address.getHostName() + System.currentTimeMillis();
- _verbose = verbose;
- _persistent = persistent;
- setPubSub(pubsub);
- // Connect to the broker.
- setConnection(new AMQConnection(brokerDetails, username, password, clientId, virtualpath));
- _logger.info("Connected with URL:" + getConnection().toURL());
-
- // Set up the failover notifier.
- getConnection().setConnectionListener(new FailoverNotifier());
-
- // Create a controlSession to listen for messages on and one to send replies on, transactional depending on the
- // command line option.
- _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
- _producerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
-
- // Create the queue to listen for message on.
- createConsumerDestination(destinationName);
- MessageConsumer consumer =
- _consumerSession.createConsumer(_consumerDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector);
-
- // Create a producer for the replies, without a default destination.
- _replyProducer = _producerSession.createProducer(null);
- _replyProducer.setDisableMessageTimestamp(true);
- _replyProducer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
- // Set this up to listen for messages on the queue.
- consumer.setMessageListener(this);
- }
-
- /**
- * Starts a stand alone ping-pong client running in verbose mode.
- *
- * @param args
- */
- public static void main(String[] args) throws Exception
- {
- System.out.println("Starting...");
-
- // Display help on the command line.
- if (args.length == 0)
- {
- _logger.info("Running test with default values...");
- //usage();
- //System.exit(0);
- }
-
- // Extract all command line parameters.
- Config config = new Config();
- config.setOptions(args);
- String brokerDetails = config.getHost() + ":" + config.getPort();
- String virtualpath = "test";
- String destinationName = config.getDestination();
- if (destinationName == null)
- {
- destinationName = DEFAULT_DESTINATION_NAME;
- }
-
- String selector = config.getSelector();
- boolean transacted = config.isTransacted();
- boolean persistent = config.usePersistentMessages();
- boolean pubsub = config.isPubSub();
- boolean verbose = true;
-
- //String selector = null;
-
- // Instantiate the ping pong client with the command line options and start it running.
- PingPongBouncer pingBouncer =
- new PingPongBouncer(brokerDetails, "guest", "guest", virtualpath, destinationName, persistent, transacted,
- selector, verbose, pubsub);
- pingBouncer.getConnection().start();
-
- System.out.println("Waiting...");
- }
-
- private static void usage()
- {
- System.err.println("Usage: PingPongBouncer \n" + "-host : broker host\n" + "-port : broker port\n"
- + "-destinationname : queue/topic name\n" + "-transacted : (true/false). Default is false\n"
- + "-persistent : (true/false). Default is false\n"
- + "-pubsub : (true/false). Default is false\n" + "-selector : selector string\n");
- }
-
- /**
- * This is a callback method that is notified of all messages for which this has been registered as a message
- * listener on a message consumer. It sends a reply (pong) to all messages it receieves on the reply to
- * destination of the message.
- *
- * @param message The message that triggered this callback.
- */
- public void onMessage(Message message)
- {
- try
- {
- String messageCorrelationId = message.getJMSCorrelationID();
- if (_verbose)
- {
- _logger.info(timestampFormatter.format(new Date()) + ": Got ping with correlation id, "
- + messageCorrelationId);
- }
-
- // Get the reply to destination from the message and check it is set.
- Destination responseDest = message.getJMSReplyTo();
-
- if (responseDest == null)
- {
- _logger.debug("Cannot send reply because reply-to destination is null.");
-
- return;
- }
-
- // Spew out some timing information if verbose mode is on.
- if (_verbose)
- {
- Long timestamp = message.getLongProperty("timestamp");
-
- if (timestamp != null)
- {
- long diff = System.currentTimeMillis() - timestamp;
- _logger.info("Time to bounce point: " + diff);
- }
- }
-
- // Correlate the reply to the original.
- message.setJMSCorrelationID(messageCorrelationId);
-
- // Send the receieved message as the pong reply.
- _replyProducer.send(responseDest, message);
-
- if (_verbose)
- {
- _logger.info(timestampFormatter.format(new Date()) + ": Sent reply with correlation id, "
- + messageCorrelationId);
- }
-
- // Commit the transaction if running in transactional mode.
- commitTx(_producerSession);
- }
- catch (JMSException e)
- {
- _logger.debug("There was a JMSException: " + e.getMessage(), e);
- }
- }
-
- /**
- * Gets the underlying connection that this ping client is running on.
- *
- * @return The underlying connection that this ping client is running on.
- */
- public AMQConnection getConnection()
- {
- return _connection;
- }
-
- /**
- * Sets the connection that this ping client is using.
- *
- * @param connection The ping connection.
- */
- public void setConnection(AMQConnection connection)
- {
- this._connection = connection;
- }
-
- /**
- * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic.
- *
- * @param pubsub <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public void setPubSub(boolean pubsub)
- {
- _isPubSub = pubsub;
- }
-
- /**
- * Checks whether this client is a p2p or pub/sub ping client.
- *
- * @return <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
- */
- public boolean isPubSub()
- {
- return _isPubSub;
- }
-
- /**
- * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not
- * a transactional controlSession, this method does nothing.
- *
- * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
- * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
- * after the commit is applied.
- *
- * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
- */
- protected void commitTx(Session session) throws JMSException
- {
- if (session.getTransacted())
- {
- try
- {
- if (_failBeforeCommit)
- {
- _logger.debug("Failing Before Commit");
- doFailover();
- }
-
- session.commit();
-
- if (_failAfterCommit)
- {
- _logger.debug("Failing After Commit");
- doFailover();
- }
-
- _logger.debug("Session Commited.");
- }
- catch (JMSException e)
- {
- _logger.trace("JMSException on commit:" + e.getMessage(), e);
-
- try
- {
- session.rollback();
- _logger.debug("Message rolled back.");
- }
- catch (JMSException jmse)
- {
- _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
-
- // Both commit and rollback failed. Throw the rollback exception.
- throw jmse;
- }
- }
- }
- }
-
- /**
- * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- *
- * @param broker The name of the broker to terminate.
- */
- protected void doFailover(String broker)
- {
- System.out.println("Kill Broker " + broker + " now.");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
- }
-
- /**
- * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
- * until the user supplied some input on the terminal.
- */
- protected void doFailover()
- {
- System.out.println("Kill Broker now.");
- try
- {
- System.in.read();
- }
- catch (IOException e)
- { }
-
- System.out.println("Continuing.");
-
- }
-
- private void createConsumerDestination(String name)
- {
- if (isPubSub())
- {
- _consumerDestination = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, name);
- }
- else
- {
- _consumerDestination = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, name);
- }
- }
-
- /**
- * A connection listener that logs out any failover complete events. Could do more interesting things with this
- * at some point...
- */
- public static class FailoverNotifier implements ConnectionListener
- {
- public void bytesSent(long count)
- { }
-
- public void bytesReceived(long count)
- { }
-
- public boolean preFailover(boolean redirect)
- {
- return true;
- }
-
- public boolean preResubscribe()
- {
- return true;
- }
-
- public void failoverComplete()
- {
- _logger.info("App got failover complete callback.");
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.requestreply;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.jms.*;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.AMQTopic;
+import org.apache.qpid.jms.ConnectionListener;
+import org.apache.qpid.jms.Session;
+import org.apache.qpid.topic.Config;
+import org.apache.qpid.exchange.ExchangeDefaults;
+
+/**
+ * PingPongBouncer is a message listener the bounces back messages to their reply to destination. This is used to return
+ * ping messages generated by {@link org.apache.qpid.requestreply.PingPongProducer} but could be used for other purposes
+ * too.
+ *
+ * <p/>The correlation id from the received message is extracted, and placed into the reply as the correlation id. Messages
+ * are bounced back to their reply-to destination. The original sender of the message has the option to use either a unique
+ * temporary queue or the correlation id to correlate the original message to the reply.
+ *
+ * <p/>There is a verbose mode flag which causes information about each ping to be output to the console
+ * (info level logging, so usually console). This can be helpfull to check the bounce backs are happening but should
+ * be disabled for real timing tests as writing to the console will slow things down.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Bounce back messages to their reply to destination.
+ * <tr><td> Provide command line invocation to start the bounce back on a configurable broker url.
+ * </table>
+ *
+ * @todo Replace the command line parsing with a neater tool.
+ *
+ * @todo Make verbose accept a number of messages, only prints to console every X messages.
+ */
+public class PingPongBouncer implements MessageListener
+{
+ private static final Logger _logger = Logger.getLogger(PingPongBouncer.class);
+
+ /** The default prefetch size for the message consumer. */
+ private static final int PREFETCH = 1;
+
+ /** The default no local flag for the message consumer. */
+ private static final boolean NO_LOCAL = true;
+
+ private static final String DEFAULT_DESTINATION_NAME = "ping";
+
+ /** The default exclusive flag for the message consumer. */
+ private static final boolean EXCLUSIVE = false;
+
+ /** A convenient formatter to use when time stamping output. */
+ protected static final SimpleDateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
+
+ /** Used to indicate that the reply generator should log timing info to the console (logger info level). */
+ private boolean _verbose = false;
+
+ /** Determines whether this bounce back client bounces back messages persistently. */
+ private boolean _persistent = false;
+
+ private Destination _consumerDestination;
+
+ /** Keeps track of the response destination of the previous message for the last reply to producer cache. */
+ private Destination _lastResponseDest;
+
+ /** The producer for sending replies with. */
+ private MessageProducer _replyProducer;
+
+ /** The consumer controlSession. */
+ private Session _consumerSession;
+
+ /** The producer controlSession. */
+ private Session _producerSession;
+
+ /** Holds the connection to the broker. */
+ private AMQConnection _connection;
+
+ /** Flag used to indicate if this is a point to point or pub/sub ping client. */
+ private boolean _isPubSub = false;
+
+ /**
+ * This flag is used to indicate that the user should be prompted to kill a broker, in order to test
+ * failover, immediately before committing a transaction.
+ */
+ protected boolean _failBeforeCommit = false;
+
+ /**
+ * This flag is used to indicate that the user should be prompted to a kill a broker, in order to test
+ * failover, immediate after committing a transaction.
+ */
+ protected boolean _failAfterCommit = false;
+
+ /**
+ * Creates a PingPongBouncer on the specified producer and consumer sessions.
+ *
+ * @param brokerDetails The addresses of the brokers to connect to.
+ * @param username The broker username.
+ * @param password The broker password.
+ * @param virtualpath The virtual host name within the broker.
+ * @param destinationName The name of the queue to receive pings on
+ * (or root of the queue name where many queues are generated).
+ * @param persistent A flag to indicate that persistent message should be used.
+ * @param transacted A flag to indicate that pings should be sent within transactions.
+ * @param selector A message selector to filter received pings with.
+ * @param verbose A flag to indicate that message timings should be sent to the console.
+ *
+ * @throws Exception All underlying exceptions allowed to fall through. This is only test code...
+ */
+ public PingPongBouncer(String brokerDetails, String username, String password, String virtualpath,
+ String destinationName, boolean persistent, boolean transacted, String selector, boolean verbose,
+ boolean pubsub) throws Exception
+ {
+ // Create a client id to uniquely identify this client.
+ InetAddress address = InetAddress.getLocalHost();
+ String clientId = address.getHostName() + System.currentTimeMillis();
+ _verbose = verbose;
+ _persistent = persistent;
+ setPubSub(pubsub);
+ // Connect to the broker.
+ setConnection(new AMQConnection(brokerDetails, username, password, clientId, virtualpath));
+ _logger.info("Connected with URL:" + getConnection().toURL());
+
+ // Set up the failover notifier.
+ getConnection().setConnectionListener(new FailoverNotifier());
+
+ // Create a controlSession to listen for messages on and one to send replies on, transactional depending on the
+ // command line option.
+ _consumerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
+ _producerSession = (Session) getConnection().createSession(transacted, Session.AUTO_ACKNOWLEDGE);
+
+ // Create the queue to listen for message on.
+ createConsumerDestination(destinationName);
+ MessageConsumer consumer =
+ _consumerSession.createConsumer(_consumerDestination, PREFETCH, NO_LOCAL, EXCLUSIVE, selector);
+
+ // Create a producer for the replies, without a default destination.
+ _replyProducer = _producerSession.createProducer(null);
+ _replyProducer.setDisableMessageTimestamp(true);
+ _replyProducer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ // Set this up to listen for messages on the queue.
+ consumer.setMessageListener(this);
+ }
+
+ /**
+ * Starts a stand alone ping-pong client running in verbose mode.
+ *
+ * @param args
+ */
+ public static void main(String[] args) throws Exception
+ {
+ System.out.println("Starting...");
+
+ // Display help on the command line.
+ if (args.length == 0)
+ {
+ _logger.info("Running test with default values...");
+ //usage();
+ //System.exit(0);
+ }
+
+ // Extract all command line parameters.
+ Config config = new Config();
+ config.setOptions(args);
+ String brokerDetails = config.getHost() + ":" + config.getPort();
+ String virtualpath = "test";
+ String destinationName = config.getDestination();
+ if (destinationName == null)
+ {
+ destinationName = DEFAULT_DESTINATION_NAME;
+ }
+
+ String selector = config.getSelector();
+ boolean transacted = config.isTransacted();
+ boolean persistent = config.usePersistentMessages();
+ boolean pubsub = config.isPubSub();
+ boolean verbose = true;
+
+ //String selector = null;
+
+ // Instantiate the ping pong client with the command line options and start it running.
+ PingPongBouncer pingBouncer =
+ new PingPongBouncer(brokerDetails, "guest", "guest", virtualpath, destinationName, persistent, transacted,
+ selector, verbose, pubsub);
+ pingBouncer.getConnection().start();
+
+ System.out.println("Waiting...");
+ }
+
+ private static void usage()
+ {
+ System.err.println("Usage: PingPongBouncer \n" + "-host : broker host\n" + "-port : broker port\n"
+ + "-destinationname : queue/topic name\n" + "-transacted : (true/false). Default is false\n"
+ + "-persistent : (true/false). Default is false\n"
+ + "-pubsub : (true/false). Default is false\n" + "-selector : selector string\n");
+ }
+
+ /**
+ * This is a callback method that is notified of all messages for which this has been registered as a message
+ * listener on a message consumer. It sends a reply (pong) to all messages it receieves on the reply to
+ * destination of the message.
+ *
+ * @param message The message that triggered this callback.
+ */
+ public void onMessage(Message message)
+ {
+ try
+ {
+ String messageCorrelationId = message.getJMSCorrelationID();
+ if (_verbose)
+ {
+ _logger.info(timestampFormatter.format(new Date()) + ": Got ping with correlation id, "
+ + messageCorrelationId);
+ }
+
+ // Get the reply to destination from the message and check it is set.
+ Destination responseDest = message.getJMSReplyTo();
+
+ if (responseDest == null)
+ {
+ _logger.debug("Cannot send reply because reply-to destination is null.");
+
+ return;
+ }
+
+ // Spew out some timing information if verbose mode is on.
+ if (_verbose)
+ {
+ Long timestamp = message.getLongProperty("timestamp");
+
+ if (timestamp != null)
+ {
+ long diff = System.currentTimeMillis() - timestamp;
+ _logger.info("Time to bounce point: " + diff);
+ }
+ }
+
+ // Correlate the reply to the original.
+ message.setJMSCorrelationID(messageCorrelationId);
+
+ // Send the receieved message as the pong reply.
+ _replyProducer.send(responseDest, message);
+
+ if (_verbose)
+ {
+ _logger.info(timestampFormatter.format(new Date()) + ": Sent reply with correlation id, "
+ + messageCorrelationId);
+ }
+
+ // Commit the transaction if running in transactional mode.
+ commitTx(_producerSession);
+ }
+ catch (JMSException e)
+ {
+ _logger.debug("There was a JMSException: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Gets the underlying connection that this ping client is running on.
+ *
+ * @return The underlying connection that this ping client is running on.
+ */
+ public AMQConnection getConnection()
+ {
+ return _connection;
+ }
+
+ /**
+ * Sets the connection that this ping client is using.
+ *
+ * @param connection The ping connection.
+ */
+ public void setConnection(AMQConnection connection)
+ {
+ this._connection = connection;
+ }
+
+ /**
+ * Sets or clears the pub/sub flag to indiciate whether this client is pinging a queue or a topic.
+ *
+ * @param pubsub <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
+ */
+ public void setPubSub(boolean pubsub)
+ {
+ _isPubSub = pubsub;
+ }
+
+ /**
+ * Checks whether this client is a p2p or pub/sub ping client.
+ *
+ * @return <tt>true</tt> if this client is pinging a topic, <tt>false</tt> if it is pinging a queue.
+ */
+ public boolean isPubSub()
+ {
+ return _isPubSub;
+ }
+
+ /**
+ * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not
+ * a transactional controlSession, this method does nothing.
+ *
+ * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the
+ * commit is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker
+ * after the commit is applied.
+ *
+ * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
+ */
+ protected void commitTx(Session session) throws JMSException
+ {
+ if (session.getTransacted())
+ {
+ try
+ {
+ if (_failBeforeCommit)
+ {
+ _logger.debug("Failing Before Commit");
+ doFailover();
+ }
+
+ session.commit();
+
+ if (_failAfterCommit)
+ {
+ _logger.debug("Failing After Commit");
+ doFailover();
+ }
+
+ _logger.debug("Session Commited.");
+ }
+ catch (JMSException e)
+ {
+ _logger.trace("JMSException on commit:" + e.getMessage(), e);
+
+ try
+ {
+ session.rollback();
+ _logger.debug("Message rolled back.");
+ }
+ catch (JMSException jmse)
+ {
+ _logger.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
+
+ // Both commit and rollback failed. Throw the rollback exception.
+ throw jmse;
+ }
+ }
+ }
+ }
+
+ /**
+ * Prompts the user to terminate the named broker, in order to test failover functionality. This method will block
+ * until the user supplied some input on the terminal.
+ *
+ * @param broker The name of the broker to terminate.
+ */
+ protected void doFailover(String broker)
+ {
+ System.out.println("Kill Broker " + broker + " now.");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ { }
+
+ System.out.println("Continuing.");
+ }
+
+ /**
+ * Prompts the user to terminate the broker, in order to test failover functionality. This method will block
+ * until the user supplied some input on the terminal.
+ */
+ protected void doFailover()
+ {
+ System.out.println("Kill Broker now.");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ { }
+
+ System.out.println("Continuing.");
+
+ }
+
+ private void createConsumerDestination(String name)
+ {
+ if (isPubSub())
+ {
+ _consumerDestination = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, name);
+ }
+ else
+ {
+ _consumerDestination = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, name);
+ }
+ }
+
+ /**
+ * A connection listener that logs out any failover complete events. Could do more interesting things with this
+ * at some point...
+ */
+ public static class FailoverNotifier implements ConnectionListener
+ {
+ public void bytesSent(long count)
+ { }
+
+ public void bytesReceived(long count)
+ { }
+
+ public boolean preFailover(boolean redirect)
+ {
+ return true;
+ }
+
+ public boolean preResubscribe()
+ {
+ return true;
+ }
+
+ public void failoverComplete()
+ {
+ _logger.info("App got failover complete callback.");
+ }
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
index f328675488..4d8a736ec8 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java
@@ -1,1720 +1,1720 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.requestreply;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-
-import org.apache.qpid.test.framework.TestUtils;
-
-import org.apache.qpid.junit.extensions.BatchedThrottle;
-import org.apache.qpid.junit.extensions.Throttle;
-import org.apache.qpid.junit.extensions.util.CommandLineParser;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.*;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-
-import java.io.*;
-import java.net.InetAddress;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * PingPongProducer is a client that sends test messages, and waits for replies to these messages. The replies may
- * either be generated by another client (see {@link PingPongBouncer}, or an extension of it may be used that listens
- * to its own messages and does not send replies (see {@link org.apache.qpid.ping.PingClient}). The intention of ping
- * pong producer is that it is a swiss-army knife test client that makes almost every aspect of its behaviour
- * configurable.
- *
- * <p/>The pings are sent with a reply-to field set to a single temporary queue, which is the same for all pings. This
- * means that this class has to do some work to correlate pings with pongs; it expectes the original message correlation
- * id in the ping to be bounced back in the reply correlation id.
- *
- * <p/>This ping tool accepts a vast number of configuration options, all of which are passed in to the constructor. It
- * can ping topics or queues; ping multiple destinations; do persistent pings; send messages of any size; do pings within
- * transactions; control the number of pings to send in each transaction; limit its sending rate; and perform failover
- * testing. A complete list of accepted parameters, default values and comments on their usage is provided here:
- *
- * <p/><table><caption>Parameters</caption>
- * <tr><th> Parameter <th> Default <th> Comments
- * <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
- * <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
- * <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
- * <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
- * <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
- * <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
- * <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
- * <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
- * <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
- * <tr><td> failAfterCommit <td> false <td> Whether to prompt user to kill broker after a commit batch.
- * <tr><td> failBeforeCommit <td> false <td> Whether to prompt user to kill broker before a commit batch.
- * <tr><td> failAfterSend <td> false <td> Whether to prompt user to kill broker after a send.
- * <tr><td> failBeforeSend <td> false <td> Whether to prompt user to kill broker before a send.
- * <tr><td> failOnce <td> true <td> Whether to prompt for failover only once.
- * <tr><td> username <td> guest <td> The username to access the broker with.
- * <tr><td> password <td> guest <td> The password to access the broker with.
- * <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
- * <tr><td> destinationCount <td> 1 <td> The number of destinations to send pings to.
- * <tr><td> numConsumers <td> 1 <td> The number of consumers on each destination.
- * <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
- * <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
- * <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
- * <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
- * <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
- * 0 - SESSION_TRANSACTED
- * 1 - AUTO_ACKNOWLEDGE
- * 2 - CLIENT_ACKNOWLEDGE
- * 3 - DUPS_OK_ACKNOWLEDGE
- * 257 - NO_ACKNOWLEDGE
- * 258 - PRE_ACKNOWLEDGE
- * <tr><td> consTransacted <td> false <td> Whether or not consumers use transactions. Defaults to the same value
- * as the 'transacted' option if not seperately defined.
- * <tr><td> consAckMode <td> AUTO_ACK <td> The message acknowledgement mode for consumers. Defaults to the same
- * value as 'ackMode' if not seperately defined.
- * <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
- * Limits the volume of messages currently buffered on the client
- * or broker. Can help scale test clients by limiting amount of buffered
- * data to avoid out of memory errors.
- * </table>
- *
- * <p/>This implements the Runnable interface with a run method that implements an infinite ping loop. The ping loop
- * does all its work through helper methods, so that code wishing to run a ping-pong cycle is not forced to do so by
- * starting a new thread. The command line invocation does take advantage of this ping loop. A shutdown hook is also
- * registered to terminate the ping-pong loop cleanly.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a ping and wait for all responses cycle.
- * <tr><td> Provide command line invocation to loop the ping cycle on a configurable broker url.
- * </table>
- *
- * @todo Use read/write lock in the onmessage, not for reading writing but to make use of a shared and exlcusive lock pair.
- * Obtain read lock on all messages, before decrementing the message count. At the end of the on message method add a
- * block that obtains the write lock for the very last message, releases any waiting producer. Means that the last
- * message waits until all other messages have been handled before releasing producers but allows messages to be
- * processed concurrently, unlike the current synchronized block.
- */
-public class PingPongProducer implements Runnable, ExceptionListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(PingPongProducer.class);
-
- /** Holds the name of the property to determine whether of not client id is overridden at connection time. */
- public static final String OVERRIDE_CLIENT_ID_PROPNAME = "overrideClientId";
-
- /** Holds the default value of the override client id flag. */
- public static final String OVERRIDE_CLIENT_ID_DEAFULT = "false";
-
- /** Holds the name of the property to define the JNDI factory name with. */
- public static final String FACTORY_NAME_PROPNAME = "factoryName";
-
- /** Holds the default JNDI name of the connection factory. */
- public static final String FACTORY_NAME_DEAFULT = "local";
-
- /** Holds the name of the property to set the JNDI initial context properties with. */
- public static final String FILE_PROPERTIES_PROPNAME = "properties";
-
- /** Holds the default file name of the JNDI initial context properties. */
- public static final String FILE_PROPERTIES_DEAFULT = "perftests.properties";
-
- /** Holds the name of the property to get the test message size from. */
- public static final String MESSAGE_SIZE_PROPNAME = "messageSize";
-
- /** Used to set up a default message size. */
- public static final int MESSAGE_SIZE_DEAFULT = 0;
-
- /** Holds the name of the property to get the ping queue name from. */
- public static final String PING_QUEUE_NAME_PROPNAME = "destinationName";
-
- /** Holds the name of the default destination to send pings on. */
- public static final String PING_QUEUE_NAME_DEFAULT = "ping";
-
- /** Holds the name of the property to get the queue name postfix from. */
- public static final String QUEUE_NAME_POSTFIX_PROPNAME = "queueNamePostfix";
-
- /** Holds the default queue name postfix value. */
- public static final String QUEUE_NAME_POSTFIX_DEFAULT = "";
-
- /** Holds the name of the property to get the test delivery mode from. */
- public static final String PERSISTENT_MODE_PROPNAME = "persistent";
-
- /** Holds the message delivery mode to use for the test. */
- public static final boolean PERSISTENT_MODE_DEFAULT = false;
-
- /** Holds the name of the property to get the test transactional mode from. */
- public static final String TRANSACTED_PROPNAME = "transacted";
-
- /** Holds the transactional mode to use for the test. */
- public static final boolean TRANSACTED_DEFAULT = false;
-
- /** Holds the name of the property to get the test consumer transacted mode from. */
- public static final String CONSUMER_TRANSACTED_PROPNAME = "consTransacted";
-
- /** Holds the consumer transactional mode default setting. */
- public static final boolean CONSUMER_TRANSACTED_DEFAULT = false;
-
- /** Holds the name of the property to get the test broker url from. */
- public static final String BROKER_PROPNAME = "broker";
-
- /** Holds the default broker url for the test. */
- public static final String BROKER_DEFAULT = "tcp://localhost:5672";
-
- /** Holds the name of the property to get the test broker virtual path. */
- public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
-
- /** Holds the default virtual path for the test. */
- public static final String VIRTUAL_HOST_DEFAULT = "";
-
- /** Holds the name of the property to get the message rate from. */
- public static final String RATE_PROPNAME = "rate";
-
- /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
- public static final int RATE_DEFAULT = 0;
-
- /** Holds the name of the property to get the verbose mode proeprty from. */
- public static final String VERBOSE_PROPNAME = "verbose";
-
- /** Holds the default verbose mode. */
- public static final boolean VERBOSE_DEFAULT = false;
-
- /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */
- public static final String PUBSUB_PROPNAME = "pubsub";
-
- /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
- public static final boolean PUBSUB_DEFAULT = false;
-
- /** Holds the name of the property to get the fail after commit flag from. */
- public static final String FAIL_AFTER_COMMIT_PROPNAME = "failAfterCommit";
-
- /** Holds the default failover after commit test flag. */
- public static final boolean FAIL_AFTER_COMMIT_DEFAULT = false;
-
- /** Holds the name of the proeprty to get the fail before commit flag from. */
- public static final String FAIL_BEFORE_COMMIT_PROPNAME = "failBeforeCommit";
-
- /** Holds the default failover before commit test flag. */
- public static final boolean FAIL_BEFORE_COMMIT_DEFAULT = false;
-
- /** Holds the name of the proeprty to get the fail after send flag from. */
- public static final String FAIL_AFTER_SEND_PROPNAME = "failAfterSend";
-
- /** Holds the default failover after send test flag. */
- public static final boolean FAIL_AFTER_SEND_DEFAULT = false;
-
- /** Holds the name of the property to get the fail before send flag from. */
- public static final String FAIL_BEFORE_SEND_PROPNAME = "failBeforeSend";
-
- /** Holds the default failover before send test flag. */
- public static final boolean FAIL_BEFORE_SEND_DEFAULT = false;
-
- /** Holds the name of the property to get the fail once flag from. */
- public static final String FAIL_ONCE_PROPNAME = "failOnce";
-
- /** The default failover once flag, true means only do one failover, false means failover on every commit cycle. */
- public static final boolean FAIL_ONCE_DEFAULT = true;
-
- /** Holds the name of the property to get the broker access username from. */
- public static final String USERNAME_PROPNAME = "username";
-
- /** Holds the default broker log on username. */
- public static final String USERNAME_DEFAULT = "guest";
-
- /** Holds the name of the property to get the broker access password from. */
- public static final String PASSWORD_PROPNAME = "password";
-
- /** Holds the default broker log on password. */
- public static final String PASSWORD_DEFAULT = "guest";
-
- /** Holds the name of the proeprty to get the. */
- public static final String SELECTOR_PROPNAME = "selector";
-
- /** Holds the default message selector. */
- public static final String SELECTOR_DEFAULT = "";
-
- /** Holds the name of the property to get the destination count from. */
- public static final String DESTINATION_COUNT_PROPNAME = "destinationCount";
-
- /** Defines the default number of destinations to ping. */
- public static final int DESTINATION_COUNT_DEFAULT = 1;
-
- /** Holds the name of the property to get the number of consumers per destination from. */
- public static final String NUM_CONSUMERS_PROPNAME = "numConsumers";
-
- /** Defines the default number consumers per destination. */
- public static final int NUM_CONSUMERS_DEFAULT = 1;
-
- /** Holds the name of the property to get the waiting timeout for response messages. */
- public static final String TIMEOUT_PROPNAME = "timeout";
-
- /** Default time to wait before assuming that a ping has timed out. */
- public static final long TIMEOUT_DEFAULT = 30000;
-
- /** Holds the name of the property to get the commit batch size from. */
- public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
-
- /** Defines the default number of pings to send in each transaction when running transactionally. */
- public static final int TX_BATCH_SIZE_DEFAULT = 1;
-
- /** Holds the name of the property to get the unique destinations flag from. */
- public static final String UNIQUE_DESTS_PROPNAME = "uniqueDests";
-
- /** Defines the default value for the unique destinations property. */
- public static final boolean UNIQUE_DESTS_DEFAULT = true;
-
- /** Holds the name of the property to get the durable destinations flag from. */
- public static final String DURABLE_DESTS_PROPNAME = "durableDests";
-
- /** Defines the default value of the durable destinations flag. */
- public static final boolean DURABLE_DESTS_DEFAULT = false;
-
- /** Holds the name of the proeprty to get the message acknowledgement mode from. */
- public static final String ACK_MODE_PROPNAME = "ackMode";
-
- /** Defines the default message acknowledgement mode. */
- public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
-
- /** Holds the name of the property to get the consumers message acknowledgement mode from. */
- public static final String CONSUMER_ACK_MODE_PROPNAME = "consAckMode";
-
- /** Defines the default consumers message acknowledgement mode. */
- public static final int CONSUMER_ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
-
- /** Holds the name of the property to get the maximum pending message size setting from. */
- public static final String MAX_PENDING_PROPNAME = "maxPending";
-
- /** Defines the default value for the maximum pending message size setting. 0 means no limit. */
- public static final int MAX_PENDING_DEFAULT = 0;
-
- /** Defines the default prefetch size to use when consuming messages. */
- public static final int PREFETCH_DEFAULT = 100;
-
- /** Defines the default value of the no local flag to use when consuming messages. */
- public static final boolean NO_LOCAL_DEFAULT = false;
-
- /** Defines the default value of the exclusive flag to use when consuming messages. */
- public static final boolean EXCLUSIVE_DEFAULT = false;
-
- /** Holds the name of the property to store nanosecond timestamps in ping messages with. */
- public static final String MESSAGE_TIMESTAMP_PROPNAME = "timestamp";
-
- /** Holds the default configuration properties. */
- public static ParsedProperties defaults = new ParsedProperties();
-
- static
- {
- defaults.setPropertyIfNull(OVERRIDE_CLIENT_ID_PROPNAME, OVERRIDE_CLIENT_ID_DEAFULT);
- defaults.setPropertyIfNull(FILE_PROPERTIES_PROPNAME, FILE_PROPERTIES_DEAFULT);
- defaults.setPropertyIfNull(FACTORY_NAME_PROPNAME, FACTORY_NAME_DEAFULT);
- defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
- defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
- defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
- defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
- defaults.setPropertyIfNull(PING_QUEUE_NAME_PROPNAME, PING_QUEUE_NAME_DEFAULT);
- defaults.setPropertyIfNull(QUEUE_NAME_POSTFIX_PROPNAME, QUEUE_NAME_POSTFIX_DEFAULT);
- defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
- defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
- defaults.setPropertyIfNull(CONSUMER_TRANSACTED_PROPNAME, CONSUMER_TRANSACTED_DEFAULT);
- defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
- defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
- defaults.setPropertyIfNull(CONSUMER_ACK_MODE_PROPNAME, CONSUMER_ACK_MODE_DEFAULT);
- defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
- defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
- defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
- defaults.setPropertyIfNull(UNIQUE_DESTS_PROPNAME, UNIQUE_DESTS_DEFAULT);
- defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
- defaults.setPropertyIfNull(FAIL_BEFORE_COMMIT_PROPNAME, FAIL_BEFORE_COMMIT_DEFAULT);
- defaults.setPropertyIfNull(FAIL_AFTER_COMMIT_PROPNAME, FAIL_AFTER_COMMIT_DEFAULT);
- defaults.setPropertyIfNull(FAIL_BEFORE_SEND_PROPNAME, FAIL_BEFORE_SEND_DEFAULT);
- defaults.setPropertyIfNull(FAIL_AFTER_SEND_PROPNAME, FAIL_AFTER_SEND_DEFAULT);
- defaults.setPropertyIfNull(FAIL_ONCE_PROPNAME, FAIL_ONCE_DEFAULT);
- defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
- defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
- defaults.setPropertyIfNull(NUM_CONSUMERS_PROPNAME, NUM_CONSUMERS_DEFAULT);
- defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
- defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
- defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
- }
-
- /** Allows setting of client ID on the connection, rather than through the connection URL. */
- protected boolean _overrideClientId;
-
- /** Holds the JNDI name of the JMS connection factory. */
- protected String _factoryName;
-
- /** Holds the name of the properties file to configure JNDI with. */
- protected String _fileProperties;
-
- /** Holds the broker url. */
- protected String _brokerDetails;
-
- /** Holds the username to access the broker with. */
- protected String _username;
-
- /** Holds the password to access the broker with. */
- protected String _password;
-
- /** Holds the virtual host on the broker to run the tests through. */
- protected String _virtualpath;
-
- /** Holds the root name from which to generate test destination names. */
- protected String _destinationName;
-
- /** Holds the default queue name postfix value. */
- protected String _queueNamePostfix;
-
- /** Holds the message selector to filter the pings with. */
- protected String _selector;
-
- /** Holds the producers transactional mode flag. */
- protected boolean _transacted;
-
- /** Holds the consumers transactional mode flag. */
- protected boolean _consTransacted;
-
- /** Determines whether this producer sends persistent messages. */
- protected boolean _persistent;
-
- /** Holds the acknowledgement mode used for the producers. */
- protected int _ackMode;
-
- /** Holds the acknowledgement mode setting for the consumers. */
- protected int _consAckMode;
-
- /** Determines what size of messages this producer sends. */
- protected int _messageSize;
-
- /** Used to indicate that the ping loop should print out whenever it pings. */
- protected boolean _verbose;
-
- /** Flag used to indicate if this is a point to point or pub/sub ping client. */
- protected boolean _isPubSub;
-
- /** Flag used to indicate if the destinations should be unique client. */
- protected boolean _isUnique;
-
- /** Flag used to indicate that durable destination should be used. */
- protected boolean _isDurable;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a commit. */
- protected boolean _failBeforeCommit;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a commit. */
- protected boolean _failAfterCommit;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a send. */
- protected boolean _failBeforeSend;
-
- /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a send. */
- protected boolean _failAfterSend;
-
- /** Flag used to indicate that failover prompting should only be done on the first commit, not on every commit. */
- protected boolean _failOnce;
-
- /** Holds the number of sends that should be performed in every transaction when using transactions. */
- protected int _txBatchSize;
-
- /** Holds the number of destinations to ping. */
- protected int _noOfDestinations;
-
- /** Holds the number of consumers per destination. */
- protected int _noOfConsumers;
-
- /** Holds the maximum send rate in herz. */
- protected int _rate;
-
- /**
- * Holds the size of the maximum amount of pending data that the client should buffer, sending is suspended
- * if this limit is breached.
- */
- protected int _maxPendingSize;
-
- /** A source for providing sequential unique correlation ids. These will be unique within the same JVM. */
- private static AtomicLong _correlationIdGenerator = new AtomicLong(0L);
-
- /** A source for providing sequential unqiue ids for instances of this class to be identifed with. */
- private static AtomicInteger _instanceIdGenerator = new AtomicInteger(0);
-
- /** Holds this instances unique id. */
- private int instanceId;
-
- /**
- * Holds a map from message ids to latches on which threads wait for replies. This map is shared accross multiple
- * ping producers on the same JVM.
- */
- private static Map<String, PerCorrelationId> perCorrelationIds =
- Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
-
- /** A convenient formatter to use when time stamping output. */
- protected static final DateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
-
- /** Holds the connection for the message producer. */
- protected Connection _connection;
-
- /** Holds the consumer connections. */
- protected Connection[] _consumerConnection;
-
- /** Holds the controlSession on which ping replies are received. */
- protected Session[] _consumerSession;
-
- /** Holds the producer controlSession, needed to create ping messages. */
- protected Session _producerSession;
-
- /** Holds the destination where the response messages will arrive. */
- protected Destination _replyDestination;
-
- /** Holds the set of destinations that this ping producer pings. */
- protected List<Destination> _pingDestinations;
-
- /** Used to restrict the sending rate to a specified limit. */
- protected Throttle _rateLimiter;
-
- /** Holds a message listener that this message listener chains all its messages to. */
- protected ChainedMessageListener _chainedMessageListener = null;
-
- /**
- * This id generator is used to generate ids to append to the queue name to ensure that queues can be unique when
- * creating multiple ping producers in the same JVM.
- */
- protected static AtomicInteger _queueJVMSequenceID = new AtomicInteger();
-
- /**
- * This id generator is used to generates ids that are only unique within this pinger. Creating multiple pingers
- * on the same JVM using this id generator will allow them to ping on the same queues.
- */
- protected AtomicInteger _queueSharedID = new AtomicInteger();
-
- /** Used to tell the ping loop when to terminate, it only runs while this is true. */
- protected boolean _publish = true;
-
- /** Holds the message producer to send the pings through. */
- protected MessageProducer _producer;
-
- /** Holds the message consumer to receive the ping replies through. */
- protected MessageConsumer[] _consumer;
-
- /** The prompt to display when asking the user to kill the broker for failover testing. */
- private static final String KILL_BROKER_PROMPT = "Kill broker now, then press Return.";
-
- /** Holds the name for this test client to be identified to the broker with. */
- private String _clientID;
-
- /** Keeps count of the total messages sent purely for debugging purposes. */
- private static AtomicInteger numSent = new AtomicInteger();
-
- /**
- * Holds a monitor which is used to synchronize sender and receivers threads, where the sender has elected
- * to wait until the number of unreceived message is reduced before continuing to send. This monitor is a
- * fair SynchronousQueue becuase that provides fair scheduling, to ensure that all producer threads get an
- * equal chance to produce messages.
- */
- static final SynchronousQueue _sendPauseMonitor = new SynchronousQueue(true);
-
- /** Keeps a count of the number of message currently sent but not received. */
- static AtomicInteger _unreceived = new AtomicInteger(0);
-
- /**
- * Creates a ping producer with the specified parameters, of which there are many. See the class level comments
- * for details. This constructor creates a connection to the broker and creates producer and consumer sessions on
- * it, to send and recieve its pings and replies on.
- *
- * @param overrides Properties containing any desired overrides to the defaults.
- *
- * @throws Exception Any exceptions are allowed to fall through.
- */
- public PingPongProducer(Properties overrides) throws Exception
- {
- // log.debug("public PingPongProducer(Properties overrides = " + overrides + "): called");
- instanceId = _instanceIdGenerator.getAndIncrement();
-
- // Create a set of parsed properties from the defaults overriden by the passed in values.
- ParsedProperties properties = new ParsedProperties(defaults);
- properties.putAll(overrides);
-
- // Extract the configuration properties to set the pinger up with.
- _overrideClientId = properties.getPropertyAsBoolean(OVERRIDE_CLIENT_ID_PROPNAME);
- _factoryName = properties.getProperty(FACTORY_NAME_PROPNAME);
- _fileProperties = properties.getProperty(FILE_PROPERTIES_PROPNAME);
- _brokerDetails = properties.getProperty(BROKER_PROPNAME);
- _username = properties.getProperty(USERNAME_PROPNAME);
- _password = properties.getProperty(PASSWORD_PROPNAME);
- _virtualpath = properties.getProperty(VIRTUAL_HOST_PROPNAME);
- _destinationName = properties.getProperty(PING_QUEUE_NAME_PROPNAME);
- _queueNamePostfix = properties.getProperty(QUEUE_NAME_POSTFIX_PROPNAME);
- _selector = properties.getProperty(SELECTOR_PROPNAME);
- _transacted = properties.getPropertyAsBoolean(TRANSACTED_PROPNAME);
- _consTransacted = properties.getPropertyAsBoolean(CONSUMER_TRANSACTED_PROPNAME);
- _persistent = properties.getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
- _messageSize = properties.getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
- _verbose = properties.getPropertyAsBoolean(VERBOSE_PROPNAME);
- _failAfterCommit = properties.getPropertyAsBoolean(FAIL_AFTER_COMMIT_PROPNAME);
- _failBeforeCommit = properties.getPropertyAsBoolean(FAIL_BEFORE_COMMIT_PROPNAME);
- _failAfterSend = properties.getPropertyAsBoolean(FAIL_AFTER_SEND_PROPNAME);
- _failBeforeSend = properties.getPropertyAsBoolean(FAIL_BEFORE_SEND_PROPNAME);
- _failOnce = properties.getPropertyAsBoolean(FAIL_ONCE_PROPNAME);
- _txBatchSize = properties.getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
- _noOfDestinations = properties.getPropertyAsInteger(DESTINATION_COUNT_PROPNAME);
- _noOfConsumers = properties.getPropertyAsInteger(NUM_CONSUMERS_PROPNAME);
- _rate = properties.getPropertyAsInteger(RATE_PROPNAME);
- _isPubSub = properties.getPropertyAsBoolean(PUBSUB_PROPNAME);
- _isUnique = properties.getPropertyAsBoolean(UNIQUE_DESTS_PROPNAME);
- _isDurable = properties.getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
- _ackMode = _transacted ? 0 : properties.getPropertyAsInteger(ACK_MODE_PROPNAME);
- _consAckMode = _consTransacted ? 0 : properties.getPropertyAsInteger(CONSUMER_ACK_MODE_PROPNAME);
- _maxPendingSize = properties.getPropertyAsInteger(MAX_PENDING_PROPNAME);
-
- // Check that one or more destinations were specified.
- if (_noOfDestinations < 1)
- {
- throw new IllegalArgumentException("There must be at least one destination.");
- }
-
- // Set up a throttle to control the send rate, if a rate > 0 is specified.
- if (_rate > 0)
- {
- _rateLimiter = new BatchedThrottle();
- _rateLimiter.setRate(_rate);
- }
-
- // Create the connection and message producers/consumers.
- // establishConnection(true, true);
- }
-
- /**
- * Establishes a connection to the broker and creates message consumers and producers based on the parameters
- * that this ping client was created with.
- *
- * @param producer Flag to indicate whether or not the producer should be set up.
- * @param consumer Flag to indicate whether or not the consumers should be set up.
- *
- * @throws Exception Any exceptions are allowed to fall through.
- */
- public void establishConnection(boolean producer, boolean consumer) throws Exception
- {
- // log.debug("public void establishConnection(): called");
-
- // Generate a unique identifying name for this client, based on it ip address and the current time.
- InetAddress address = InetAddress.getLocalHost();
- // _clientID = address.getHostName() + System.currentTimeMillis();
- _clientID = "perftest_" + instanceId;
-
- // Create a connection to the broker.
- createConnection(_clientID);
-
- // Create transactional or non-transactional sessions, based on the command line arguments.
- _producerSession = _connection.createSession(_transacted, _ackMode);
-
- _consumerSession = new Session[_noOfConsumers];
-
- for (int i = 0; i < _noOfConsumers; i++)
- {
- _consumerSession[i] = _consumerConnection[i].createSession(_consTransacted, _consAckMode);
- }
-
- // Create the destinations to send pings to and receive replies from.
- _replyDestination = _consumerSession[0].createTemporaryQueue();
- createPingDestinations(_noOfDestinations, _selector, _destinationName, _isUnique, _isDurable);
-
- // Create the message producer only if instructed to.
- if (producer)
- {
- createProducer();
- }
-
- // Create the message consumer only if instructed to.
- if (consumer)
- {
- createReplyConsumers(getReplyDestinations(), _selector);
- }
- }
-
- /**
- * Establishes a connection to the broker, based on the configuration parameters that this ping client was
- * created with.
- *
- * @param clientID The clients identifier.
- *
- * @throws JMSException Underlying exceptions allowed to fall through.
- * @throws NamingException Underlying exceptions allowed to fall through.
- * @throws IOException Underlying exceptions allowed to fall through.
- */
- protected void createConnection(String clientID) throws JMSException, NamingException, IOException
- {
- // _log.debug("protected void createConnection(String clientID = " + clientID + "): called");
-
- // _log.debug("Creating a connection for the message producer.");
- File propsFile = new File(_fileProperties);
- InputStream is = new FileInputStream(propsFile);
- Properties properties = new Properties();
- properties.load(is);
-
- Context context = new InitialContext(properties);
- ConnectionFactory factory = (ConnectionFactory) context.lookup(_factoryName);
- _connection = factory.createConnection(_username, _password);
-
- if (_overrideClientId)
- {
- _connection.setClientID(clientID);
- }
-
- // _log.debug("Creating " + _noOfConsumers + " connections for the consumers.");
-
- _consumerConnection = new Connection[_noOfConsumers];
-
- for (int i = 0; i < _noOfConsumers; i++)
- {
- _consumerConnection[i] = factory.createConnection(_username, _password);
- // _consumerConnection[i].setClientID(clientID);
- }
- }
-
- /**
- * Starts a ping-pong loop running from the command line. The bounce back client {@link PingPongBouncer} also needs
- * to be started to bounce the pings back again.
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- try
- {
- Properties options =
- CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
-
- // Create a ping producer overriding its defaults with all options passed on the command line.
- PingPongProducer pingProducer = new PingPongProducer(options);
- pingProducer.establishConnection(true, true);
-
- // Start the ping producers dispatch thread running.
- pingProducer._connection.start();
-
- // Create a shutdown hook to terminate the ping-pong producer.
- Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
-
- // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
- pingProducer._connection.setExceptionListener(pingProducer);
-
- // Create the ping loop thread and run it until it is terminated by the shutdown hook or exception.
- Thread pingThread = new Thread(pingProducer);
- pingThread.run();
- pingThread.join();
- }
- catch (Exception e)
- {
- System.err.println(e.getMessage());
- log.error("Top level handler caught execption.", e);
- System.exit(1);
- }
- }
-
- /**
- * Convenience method for a short pause.
- *
- * @param sleepTime The time in milliseconds to pause for.
- */
- public static void pause(long sleepTime)
- {
- if (sleepTime > 0)
- {
- try
- {
- Thread.sleep(sleepTime);
- }
- catch (InterruptedException ie)
- { }
- }
- }
-
- /**
- * Gets all the reply destinations (to listen for replies on). In this case this will just be the single reply to
- * destination of this pinger.
- *
- * @return The single reply to destination of this pinger, wrapped in a list.
- */
- public List<Destination> getReplyDestinations()
- {
- // log.debug("public List<Destination> getReplyDestinations(): called");
-
- List<Destination> replyDestinations = new ArrayList<Destination>();
- replyDestinations.add(_replyDestination);
-
- // log.debug("replyDestinations = " + replyDestinations);
-
- return replyDestinations;
- }
-
- /**
- * Creates the producer to send the pings on. This is created without a default destination. Its persistent delivery
- * flag is set accoring the ping producer creation options.
- *
- * @throws JMSException Any JMSExceptions are allowed to fall through.
- */
- public void createProducer() throws JMSException
- {
- // log.debug("public void createProducer(): called");
-
- _producer = (MessageProducer) _producerSession.createProducer(null);
- _producer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
-
- // log.debug("Created producer for " + (_persistent ? "persistent" : "non-persistent") + " messages.");
- }
-
- /**
- * Creates consumers for the specified number of destinations. The destinations themselves are also created by this
- * method.
- *
- * @param noOfDestinations The number of destinations to create consumers for.
- * @param selector The message selector to filter the consumers with.
- * @param rootName The root of the name, or actual name if only one is being created.
- * @param unique <tt>true</tt> to make the destinations unique to this pinger, <tt>false</tt> to share the
- * numbering with all pingers on the same JVM.
- * @param durable If the destinations are durable topics.
- *
- * @throws JMSException Any JMSExceptions are allowed to fall through.
- */
- public void createPingDestinations(int noOfDestinations, String selector, String rootName, boolean unique,
- boolean durable) throws JMSException
- {
- /*log.debug("public void createPingDestinations(int noOfDestinations = " + noOfDestinations + ", String selector = "
- + selector + ", String rootName = " + rootName + ", boolean unique = " + unique + ", boolean durable = "
- + durable + "): called");*/
-
- _pingDestinations = new ArrayList<Destination>();
-
- // Create the desired number of ping destinations and consumers for them.
- // log.debug("Creating " + noOfDestinations + " destinations to ping.");
-
- for (int i = 0; i < noOfDestinations; i++)
- {
- Destination destination;
- String id;
-
- // Generate an id, unique within this pinger or to the whole JVM depending on the unique flag.
- if (unique)
- {
- // log.debug("Creating unique destinations.");
- id = "_" + _queueJVMSequenceID.incrementAndGet() + "_" + _connection.getClientID();
- }
- else
- {
- // log.debug("Creating shared destinations.");
- id = "_" + _queueSharedID.incrementAndGet();
- }
-
- // Check if this is a pub/sub pinger, in which case create topics.
- if (_isPubSub)
- {
- destination = _producerSession.createTopic(rootName + id);
- // log.debug("Created non-durable topic " + destination);
-
- if (durable)
- {
- _producerSession.createDurableSubscriber((Topic) destination, _connection.getClientID());
- }
- }
- // Otherwise this is a p2p pinger, in which case create queues.
- else
- {
- destination = _producerSession.createQueue(rootName + id + _queueNamePostfix);
- // log.debug("Created queue " + destination);
- }
-
- // Keep the destination.
- _pingDestinations.add(destination);
- }
- }
-
- /**
- * Creates consumers for the specified destinations and registers this pinger to listen to their messages.
- *
- * @param destinations The destinations to listen to.
- * @param selector A selector to filter the messages with.
- *
- * @throws javax.jms.JMSException Any JMSExceptions are allowed to fall through.
- */
- public void createReplyConsumers(Collection<Destination> destinations, String selector) throws JMSException
- {
- /*log.debug("public void createReplyConsumers(Collection<Destination> destinations = " + destinations
- + ", String selector = " + selector + "): called");*/
-
- log.debug("There are " + destinations.size() + " destinations.");
- log.debug("Creating " + _noOfConsumers + " consumers on each destination.");
- log.debug("Total number of consumers is: " + (destinations.size() * _noOfConsumers));
-
- for (Destination destination : destinations)
- {
- _consumer = new MessageConsumer[_noOfConsumers];
-
- for (int i = 0; i < _noOfConsumers; i++)
- {
- // Create a consumer for the destination and set this pinger to listen to its messages.
- _consumer[i] = _consumerSession[i].createConsumer(destination, selector, NO_LOCAL_DEFAULT);
-
- final int consumerNo = i;
-
- _consumer[i].setMessageListener(new MessageListener()
- {
- public void onMessage(Message message)
- {
- onMessageWithConsumerNo(message, consumerNo);
- }
- });
-
- log.debug("Set consumer " + i + " to listen to replies sent to destination: " + destination);
- }
- }
- }
-
- /**
- * Stores the received message in the replies map, then resets the boolean latch that a thread waiting for a
- * correlating reply may be waiting on. This is only done if the reply has a correlation id that is expected in the
- * replies map.
- *
- * @param message The received message.
- * @param consumerNo The consumer number within this test pinger instance.
- */
- public void onMessageWithConsumerNo(Message message, int consumerNo)
- {
- // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo = " + consumerNo + "): called");
- try
- {
- long now = System.nanoTime();
- long timestamp = getTimestamp(message);
- long pingTime = now - timestamp;
-
- // NDC.push("id" + instanceId + "/cons" + consumerNo);
-
- // Extract the messages correlation id.
- String correlationID = message.getJMSCorrelationID();
- // log.debug("correlationID = " + correlationID);
-
- // int num = message.getIntProperty("MSG_NUM");
- // log.info("Message " + num + " received.");
-
- boolean isRedelivered = message.getJMSRedelivered();
- // log.debug("isRedelivered = " + isRedelivered);
-
- if (!isRedelivered)
- {
- // Countdown on the traffic light if there is one for the matching correlation id.
- PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID);
-
- if (perCorrelationId != null)
- {
- CountDownLatch trafficLight = perCorrelationId.trafficLight;
-
- // Restart the timeout timer on every message.
- perCorrelationId.timeOutStart = System.nanoTime();
-
- // log.debug("Reply was expected, decrementing the latch for the id, " + correlationID);
-
- // Release waiting senders if there are some and using maxPending limit.
- if ((_maxPendingSize > 0))
- {
- // Decrement the count of sent but not yet received messages.
- int unreceived = _unreceived.decrementAndGet();
- int unreceivedSize =
- (unreceived * ((_messageSize == 0) ? 1 : _messageSize))
- / (_isPubSub ? getConsumersPerDestination() : 1);
-
- // log.debug("unreceived = " + unreceived);
- // log.debug("unreceivedSize = " + unreceivedSize);
-
- // synchronized (_sendPauseMonitor)
- // {
- if (unreceivedSize < _maxPendingSize)
- {
- _sendPauseMonitor.poll();
- }
- // }
- }
-
- // Decrement the countdown latch. Before this point, it is possible that two threads might enter this
- // method simultanesouly with the same correlation id. Decrementing the latch in a synchronized block
- // ensures that each thread will get a unique value for the remaining messages.
- long trueCount;
- long remainingCount;
-
- synchronized (trafficLight)
- {
- trafficLight.countDown();
-
- trueCount = trafficLight.getCount();
- remainingCount = trueCount - 1;
-
- // NDC.push("/rem" + remainingCount);
-
- // log.debug("remainingCount = " + remainingCount);
- // log.debug("trueCount = " + trueCount);
-
- // Commit on transaction batch size boundaries. At this point in time the waiting producer
- // remains blocked, even on the last message.
- // Commit count is divided by noOfConsumers in p2p mode, so that each consumer only commits on
- // each batch boundary. For pub/sub each consumer gets every message so no division is done.
- // When running in client ack mode, an ack is done instead of a commit, on the commit batch
- // size boundaries.
- long commitCount = _isPubSub ? remainingCount : (remainingCount / _noOfConsumers);
- // log.debug("commitCount = " + commitCount);
-
- if ((commitCount % _txBatchSize) == 0)
- {
- if (_consAckMode == 2)
- {
- // log.debug("Doing client ack for consumer " + consumerNo + ".");
- message.acknowledge();
- }
- else
- {
- // log.debug("Trying commit for consumer " + consumerNo + ".");
- commitTx(_consumerSession[consumerNo]);
- // log.info("Tx committed on consumer " + consumerNo);
- }
- }
-
- // Forward the message and remaining count to any interested chained message listener.
- if (_chainedMessageListener != null)
- {
- _chainedMessageListener.onMessage(message, (int) remainingCount, pingTime);
- }
-
- // Check if this is the last message, in which case release any waiting producers. This is done
- // after the transaction has been committed and any listeners notified.
- if (trueCount == 1)
- {
- trafficLight.countDown();
- }
- }
- }
- else
- {
- log.warn("Got unexpected message with correlationId: " + correlationID);
- }
- }
- else
- {
- log.warn("Got redelivered message, ignoring.");
- }
- }
- catch (JMSException e)
- {
- log.warn("There was a JMSException: " + e.getMessage(), e);
- }
- finally
- {
- // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo): ending");
- // NDC.clear();
- }
- }
-
- /**
- * Sends the specified number of ping message and then waits for all correlating replies. If the wait times out
- * before a reply arrives, then a null reply is returned from this method. This method allows the caller to specify
- * the correlation id.
- *
- * @param message The message to send. If this is null, one is generated.
- * @param numPings The number of ping messages to send.
- * @param timeout The timeout in milliseconds.
- * @param messageCorrelationId The message correlation id. If this is null, one is generated.
- *
- * @return The number of replies received. This may be less than the number sent if the timeout terminated the wait
- * for all prematurely.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- * @throws InterruptedException When interrupted by a timeout
- */
- public int pingAndWaitForReply(Message message, int numPings, long timeout, String messageCorrelationId)
- throws JMSException, InterruptedException
- {
- /*log.debug("public int pingAndWaitForReply(Message message, int numPings = " + numPings + ", long timeout = "
- + timeout + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/
-
- // Generate a unique correlation id to put on the messages before sending them, if one was not specified.
- if (messageCorrelationId == null)
- {
- messageCorrelationId = Long.toString(_correlationIdGenerator.incrementAndGet());
- }
-
- try
- {
- // NDC.push("prod");
-
- // Create a count down latch to count the number of replies with. This is created before the messages are
- // sent so that the replies cannot be received before the count down is created.
- // One is added to this, so that the last reply becomes a special case. The special case is that the
- // chained message listener must be called before this sender can be unblocked, but that decrementing the
- // countdown needs to be done before the chained listener can be called.
- PerCorrelationId perCorrelationId = new PerCorrelationId();
-
- perCorrelationId.trafficLight = new CountDownLatch(getExpectedNumPings(numPings) + 1);
- perCorrelationIds.put(messageCorrelationId, perCorrelationId);
-
- // Set up the current time as the start time for pinging on the correlation id. This is used to determine
- // timeouts.
- perCorrelationId.timeOutStart = System.nanoTime();
-
- // Send the specifed number of messages.
- pingNoWaitForReply(message, numPings, messageCorrelationId);
-
- boolean timedOut;
- boolean allMessagesReceived;
- int numReplies;
-
- do
- {
- // Block the current thread until replies to all the messages are received, or it times out.
- perCorrelationId.trafficLight.await(timeout, TimeUnit.MILLISECONDS);
-
- // Work out how many replies were receieved.
- numReplies = getExpectedNumPings(numPings) - (int) perCorrelationId.trafficLight.getCount();
-
- allMessagesReceived = numReplies == getExpectedNumPings(numPings);
-
- // log.debug("numReplies = " + numReplies);
- // log.debug("allMessagesReceived = " + allMessagesReceived);
-
- // Recheck the timeout condition.
- long now = System.nanoTime();
- long lastMessageReceievedAt = perCorrelationId.timeOutStart;
- timedOut = (now - lastMessageReceievedAt) > (timeout * 1000000);
-
- // log.debug("now = " + now);
- // log.debug("lastMessageReceievedAt = " + lastMessageReceievedAt);
- }
- while (!timedOut && !allMessagesReceived);
-
- if ((numReplies < getExpectedNumPings(numPings)) && _verbose)
- {
- log.info("Timed out (" + timeout + " ms) before all replies received on id, " + messageCorrelationId);
- }
- else if (_verbose)
- {
- log.info("Got all replies on id, " + messageCorrelationId);
- }
-
- // commitTx(_consumerSession);
-
- // log.debug("public int pingAndWaitForReply(Message message, int numPings, long timeout): ending");
-
- return numReplies;
- }
- // Ensure that the message countdown latch is always removed from the reply map. The reply map is long lived,
- // so will be a memory leak if this is not done.
- finally
- {
- // NDC.pop();
- perCorrelationIds.remove(messageCorrelationId);
- }
- }
-
- /**
- * Sends the specified number of ping messages and does not wait for correlating replies.
- *
- * @param message The message to send.
- * @param numPings The number of pings to send.
- * @param messageCorrelationId A correlation id to place on all messages sent.
- *
- * @throws JMSException All underlying JMSExceptions are allowed to fall through.
- */
- public void pingNoWaitForReply(Message message, int numPings, String messageCorrelationId) throws JMSException
- {
- /*log.debug("public void pingNoWaitForReply(Message message, int numPings = " + numPings
- + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/
-
- if (message == null)
- {
- message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent);
- }
-
- message.setJMSCorrelationID(messageCorrelationId);
-
- // Set up a committed flag to detect uncommitted messages at the end of the send loop. This may occurr if the
- // transaction batch size is not a factor of the number of pings. In which case an extra commit at the end is
- // needed.
- boolean committed = false;
-
- // Send all of the ping messages.
- for (int i = 0; i < numPings; i++)
- {
- // Re-timestamp the message.
- // message.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
-
- // Send the message, passing in the message count.
- committed = sendMessage(i, message);
-
- // Spew out per message timings on every message sonly in verbose mode.
- /*if (_verbose)
- {
- log.info(timestampFormatter.format(new Date()) + ": Pinged at with correlation id, " + messageCorrelationId);
- }*/
- }
-
- // Call commit if the send loop finished before reaching a batch size boundary so there may still be uncommitted messages.
- if (!committed)
- {
- commitTx(_producerSession);
- }
- }
-
- /**
- * Sends the sepcified message, applies rate limiting and possibly commits the current transaction. The count of
- * messages sent so far must be specified and is used to round robin the ping destinations (where there are more
- * than one), and to determine if the transaction batch size has been reached and the sent messages should be
- * committed.
- *
- * @param i The count of messages sent so far in a loop of multiple calls to this send method.
- * @param message The message to send.
- *
- * @return <tt>true</tt> if the messages were committed, <tt>false</tt> otherwise.
- *
- * @throws JMSException All underlyiung JMSExceptions are allowed to fall through.
- */
- protected boolean sendMessage(int i, Message message) throws JMSException
- {
- try
- {
- NDC.push("id" + instanceId + "/prod");
-
- // log.debug("protected boolean sendMessage(int i = " + i + ", Message message): called");
- // log.debug("_txBatchSize = " + _txBatchSize);
-
- // Round robin the destinations as the messages are sent.
- Destination destination = _pingDestinations.get(i % _pingDestinations.size());
-
- // Prompt the user to kill the broker when doing failover testing.
- _failBeforeSend = waitForUserToPromptOnFailure(_failBeforeSend);
-
- // Get the test setup for the correlation id.
- String correlationID = message.getJMSCorrelationID();
- PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID);
-
- // If necessary, wait until the max pending message size comes within its limit.
- if (_maxPendingSize > 0)
- {
- synchronized (_sendPauseMonitor)
- {
- // Used to keep track of the number of times that send has to wait.
- int numWaits = 0;
-
- // The maximum number of waits before the test gives up and fails. This has been chosen to correspond with
- // the test timeout.
- int waitLimit = (int) (TIMEOUT_DEFAULT / 10000);
-
- while (true)
- {
- // Get the size estimate of sent but not yet received messages.
- int unreceived = _unreceived.get();
- int unreceivedSize =
- (unreceived * ((_messageSize == 0) ? 1 : _messageSize))
- / (_isPubSub ? getConsumersPerDestination() : 1);
-
- // log.debug("unreceived = " + unreceived);
- // log.debug("unreceivedSize = " + unreceivedSize);
- // log.debug("_maxPendingSize = " + _maxPendingSize);
-
- if (unreceivedSize > _maxPendingSize)
- {
- // log.debug("unreceived size estimate over limit = " + unreceivedSize);
-
- // Fail the test if the send has had to wait more than the maximum allowed number of times.
- if (numWaits > waitLimit)
- {
- String errorMessage =
- "Send has had to wait for the unreceivedSize (" + unreceivedSize
- + ") to come below the maxPendingSize (" + _maxPendingSize + ") more that " + waitLimit
- + " times.";
- log.warn(errorMessage);
- throw new RuntimeException(errorMessage);
- }
-
- // Wait on the send pause barrier for the limit to be re-established.
- try
- {
- long start = System.nanoTime();
- // _sendPauseMonitor.wait(10000);
- _sendPauseMonitor.offer(new Object(), 10000, TimeUnit.MILLISECONDS);
- long end = System.nanoTime();
-
- // Count the wait only if it was for > 99% of the requested wait time.
- if (((float) (end - start) / (float) (10000 * 1000000L)) > 0.99)
- {
- numWaits++;
- }
- }
- catch (InterruptedException e)
- {
- // Restore the interrupted status
- Thread.currentThread().interrupt();
- throw new RuntimeException(e);
- }
- }
- else
- {
- break;
- }
- }
- }
- }
-
- // Send the message either to its round robin destination, or its default destination.
- // int num = numSent.incrementAndGet();
- // message.setIntProperty("MSG_NUM", num);
- setTimestamp(message);
-
- if (destination == null)
- {
- _producer.send(message);
- }
- else
- {
- _producer.send(destination, message);
- }
-
- // Increase the unreceived size, this may actually happen after the message is received.
- // The unreceived size is incremented by the number of consumers that will get a copy of the message,
- // in pub/sub mode.
- if (_maxPendingSize > 0)
- {
- int newUnreceivedCount = _unreceived.addAndGet(_isPubSub ? getConsumersPerDestination() : 1);
- // log.debug("newUnreceivedCount = " + newUnreceivedCount);
- }
-
- // Apply message rate throttling if a rate limit has been set up.
- if (_rateLimiter != null)
- {
- _rateLimiter.throttle();
- }
-
- // Call commit every time the commit batch size is reached.
- boolean committed = false;
-
- // Commit on every transaction batch size boundary. Here i + 1 is the count of actual messages sent.
- if (((i + 1) % _txBatchSize) == 0)
- {
- // log.debug("Trying commit on producer session.");
- committed = commitTx(_producerSession);
- }
-
- return committed;
- }
- finally
- {
- NDC.clear();
- }
- }
-
- /**
- * If the specified fail flag is set, this method waits for the user to cause a failure and then indicate to the
- * test that the failure has occurred, before the method returns.
- *
- * @param failFlag The fail flag to test.
- *
- * @return The new value for the fail flag. If the {@link #_failOnce} flag is set, then each fail flag is only
- * used once, then reset.
- */
- private boolean waitForUserToPromptOnFailure(boolean failFlag)
- {
- if (failFlag)
- {
- if (_failOnce)
- {
- failFlag = false;
- }
-
- // log.debug("Failing Before Send");
- waitForUser(KILL_BROKER_PROMPT);
- }
-
- return failFlag;
- }
-
- /**
- * Implements a single iteration of the ping loop. This sends the number of pings specified by the transaction batch
- * size property, and waits for replies to all of them. Any errors cause the publish flag to be cleared, which will
- * terminate the pinger.
- */
- public void pingLoop()
- {
- try
- {
- // Generate a sample message and time stamp it.
- Message msg = getTestMessage(_replyDestination, _messageSize, _persistent);
- // setTimestamp(msg);
-
- // Send the message and wait for a reply.
- pingAndWaitForReply(msg, TX_BATCH_SIZE_DEFAULT, TIMEOUT_DEFAULT, null);
- }
- catch (JMSException e)
- {
- _publish = false;
- // log.debug("There was a JMSException: " + e.getMessage(), e);
- }
- catch (InterruptedException e)
- {
- _publish = false;
- // log.debug("There was an interruption: " + e.getMessage(), e);
- }
- }
-
- /**
- * Sets a chained message listener. The message listener on this pinger, chains all its messages to the one set
- * here.
- *
- * @param messageListener The chained message listener.
- */
- public void setChainedMessageListener(ChainedMessageListener messageListener)
- {
- _chainedMessageListener = messageListener;
- }
-
- /** Removes any chained message listeners from this pinger. */
- public void removeChainedMessageListener()
- {
- _chainedMessageListener = null;
- }
-
- /**
- * Generates a test message of the specified size, with the specified reply-to destination and persistence flag.
- *
- * @param replyQueue The reply-to destination for the message.
- * @param messageSize The desired size of the message in bytes.
- * @param persistent <tt>true</tt> if the message should use persistent delivery, <tt>false</tt> otherwise.
- *
- * @return A freshly generated test message.
- *
- * @throws javax.jms.JMSException All underlying JMSException are allowed to fall through.
- */
- public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
- {
- // return TestMessageFactory.newObjectMessage(_producerSession, replyQueue, messageSize, persistent);
- return TestUtils.createTestMessageOfSize(_producerSession, messageSize);
- }
-
- /**
- * Sets the current time in nanoseconds as the timestamp on the message.
- *
- * @param msg The message to timestamp.
- *
- * @throws JMSException Any JMSExceptions are allowed to fall through.
- */
- protected void setTimestamp(Message msg) throws JMSException
- {
- /*if (((AMQSession)_producerSession).isStrictAMQP())
- {
- ((AMQMessage)msg).setTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME), System.nanoTime());
- }
- else
- {*/
- msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
- // }
- }
-
- /**
- * Extracts the nanosecond timestamp from a message.
- *
- * @param msg The message to extract the time stamp from.
- *
- * @return The timestamp in nanos.
- *
- * @throws JMSException Any JMSExceptions are allowed to fall through.
- */
- protected long getTimestamp(Message msg) throws JMSException
- {
- /*if (((AMQSession)_producerSession).isStrictAMQP())
- {
- Long value = ((AMQMessage)msg).getTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME));
-
- return (value == null) ? 0L : value;
- }
- else
- {*/
- return msg.getLongProperty(PingPongProducer.MESSAGE_TIMESTAMP_PROPNAME);
- // }
- }
-
- /**
- * Stops the ping loop by clearing the publish flag. The current loop will complete when it notices that this flag
- * has been cleared.
- */
- public void stop()
- {
- _publish = false;
- }
-
- /**
- * Starts the producer and consumer connections.
- *
- * @throws JMSException Any JMSExceptions are allowed to fall through.
- */
- public void start() throws JMSException
- {
- // log.debug("public void start(): called");
-
- _connection.start();
- // log.debug("Producer started.");
-
- for (int i = 0; i < _noOfConsumers; i++)
- {
- _consumerConnection[i].start();
- // log.debug("Consumer " + i + " started.");
- }
- }
-
- /** Implements a ping loop that repeatedly pings until the publish flag becomes false. */
- public void run()
- {
- // Keep running until the publish flag is cleared.
- while (_publish)
- {
- pingLoop();
- }
- }
-
- /**
- * Callback method, implementing ExceptionListener. This should be registered to listen for exceptions on the
- * connection, this clears the publish flag which in turn will halt the ping loop.
- *
- * @param e The exception that triggered this callback method.
- */
- public void onException(JMSException e)
- {
- // log.debug("public void onException(JMSException e = " + e + "): called", e);
- _publish = false;
- }
-
- /**
- * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered
- * with the runtime system as a shutdown hook.
- *
- * @return A shutdown hook for the ping loop.
- */
- public Thread getShutdownHook()
- {
- return new Thread(new Runnable()
- {
- public void run()
- {
- stop();
- }
- });
- }
-
- /**
- * Closes all of the producer and consumer connections.
- *
- * @throws JMSException All JMSException are allowed to fall through.
- */
- public void close() throws JMSException
- {
- // log.debug("public void close(): called");
-
- try
- {
- if (_connection != null)
- {
- // log.debug("Before close producer connection.");
- _connection.close();
- // log.debug("Closed producer connection.");
- }
-
- for (int i = 0; i < _noOfConsumers; i++)
- {
- if (_consumerConnection[i] != null)
- {
- // log.debug("Before close consumer connection " + i + ".");
- _consumerConnection[i].close();
- // log.debug("Closed consumer connection " + i + ".");
- }
- }
- }
- finally
- {
- _connection = null;
- _producerSession = null;
- _consumerSession = null;
- _consumerConnection = null;
- _producer = null;
- _consumer = null;
- _pingDestinations = null;
- _replyDestination = null;
- }
- }
-
- /**
- * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not a
- * transactional controlSession, this method does nothing (unless the failover after send flag is set).
- *
- * <p/>If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit is
- * applied. This flag applies whether the pinger is transactional or not.
- *
- * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the commit
- * is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker after the
- * commit is applied. These flags will only apply if using a transactional pinger.
- *
- * @param session The controlSession to commit
- *
- * @return <tt>true</tt> if the controlSession was committed, <tt>false</tt> if it was not.
- *
- * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
- *
- * @todo Consider moving the fail after send logic into the send method. It is confusing to have it in this commit
- * method, because commits only apply to transactional pingers, but fail after send applied to transactional and
- * non-transactional alike.
- */
- protected boolean commitTx(Session session) throws JMSException
- {
- // log.debug("protected void commitTx(Session session): called");
-
- boolean committed = false;
-
- _failAfterSend = waitForUserToPromptOnFailure(_failAfterSend);
-
- if (session.getTransacted())
- {
- // log.debug("Session is transacted.");
-
- try
- {
- _failBeforeCommit = waitForUserToPromptOnFailure(_failBeforeCommit);
-
- long start = System.nanoTime();
- session.commit();
- committed = true;
- // log.debug("Time taken to commit :" + ((System.nanoTime() - start) / 1000000f) + " ms");
-
- _failAfterCommit = waitForUserToPromptOnFailure(_failAfterCommit);
-
- // log.debug("Session Commited.");
- }
- catch (JMSException e)
- {
- // log.debug("JMSException on commit:" + e.getMessage(), e);
-
- try
- {
- session.rollback();
- // log.debug("Message rolled back.");
- }
- catch (JMSException jmse)
- {
- // log.debug("JMSE on rollback:" + jmse.getMessage(), jmse);
-
- // Both commit and rollback failed. Throw the rollback exception.
- throw jmse;
- }
- }
- }
-
- return committed;
- }
-
- /**
- * Outputs a prompt to the console and waits for the user to press return.
- *
- * @param prompt The prompt to display on the console.
- */
- public void waitForUser(String prompt)
- {
- System.out.println(prompt);
-
- try
- {
- System.in.read();
- }
- catch (IOException e)
- {
- // Ignored.
- }
-
- System.out.println("Continuing.");
- }
-
- /**
- * Gets the number of consumers that are listening to each destination in the test.
- *
- * @return int The number of consumers subscribing to each topic.
- */
- public int getConsumersPerDestination()
- {
- return _noOfConsumers;
- }
-
- /**
- * Calculates how many pings are expected to be received for the given number sent.
- *
- * @param numpings The number of pings that will be sent.
- *
- * @return The number that should be received, for the test to pass.
- */
- public int getExpectedNumPings(int numpings)
- {
- // log.debug("public int getExpectedNumPings(int numpings = " + numpings + "): called");
-
- // log.debug("Each ping will be received by " + (_isPubSub ? getConsumersPerDestination() : 1) + " consumers.");
-
- return numpings * (_isPubSub ? getConsumersPerDestination() : 1);
- }
-
- /**
- * Defines a chained message listener interface that can be attached to this pinger. Whenever this pinger's {@link
- * PingPongProducer#onMessageWithConsumerNo} method is called, the chained listener set through the {@link
- * PingPongProducer#setChainedMessageListener} method is passed the message, and the remaining expected count of
- * messages with that correlation id.
- *
- * <p/>Provided only one pinger is producing messages with that correlation id, the chained listener will always be
- * given unique message counts. It will always be called while the producer waiting for all messages to arrive is
- * still blocked.
- */
- public static interface ChainedMessageListener
- {
- /**
- * Notifies interested listeners about message arrival and important test stats, the number of messages
- * remaining in the test, and the messages send timestamp.
- *
- * @param message The newly arrived message.
- * @param remainingCount The number of messages left to complete the test.
- * @param latency The nanosecond latency of the message.
- *
- * @throws JMSException Any JMS exceptions is allowed to fall through.
- */
- public void onMessage(Message message, int remainingCount, long latency) throws JMSException;
- }
-
- /**
- * Holds information on each correlation id. The countdown latch, the current timeout timer... More stuff to be
- * added to this: read/write lock to make onMessage more concurrent as described in class header comment.
- */
- protected static class PerCorrelationId
- {
- /** Holds a countdown on number of expected messages. */
- CountDownLatch trafficLight;
-
- /** Holds the last timestamp that the timeout was reset to. */
- Long timeOutStart;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.requestreply;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.test.framework.TestUtils;
+
+import org.apache.qpid.junit.extensions.BatchedThrottle;
+import org.apache.qpid.junit.extensions.Throttle;
+import org.apache.qpid.junit.extensions.util.CommandLineParser;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * PingPongProducer is a client that sends test messages, and waits for replies to these messages. The replies may
+ * either be generated by another client (see {@link PingPongBouncer}, or an extension of it may be used that listens
+ * to its own messages and does not send replies (see {@link org.apache.qpid.ping.PingClient}). The intention of ping
+ * pong producer is that it is a swiss-army knife test client that makes almost every aspect of its behaviour
+ * configurable.
+ *
+ * <p/>The pings are sent with a reply-to field set to a single temporary queue, which is the same for all pings. This
+ * means that this class has to do some work to correlate pings with pongs; it expectes the original message correlation
+ * id in the ping to be bounced back in the reply correlation id.
+ *
+ * <p/>This ping tool accepts a vast number of configuration options, all of which are passed in to the constructor. It
+ * can ping topics or queues; ping multiple destinations; do persistent pings; send messages of any size; do pings within
+ * transactions; control the number of pings to send in each transaction; limit its sending rate; and perform failover
+ * testing. A complete list of accepted parameters, default values and comments on their usage is provided here:
+ *
+ * <p/><table><caption>Parameters</caption>
+ * <tr><th> Parameter <th> Default <th> Comments
+ * <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
+ * <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
+ * <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
+ * <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
+ * <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ * <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
+ * <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ * <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
+ * <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
+ * <tr><td> failAfterCommit <td> false <td> Whether to prompt user to kill broker after a commit batch.
+ * <tr><td> failBeforeCommit <td> false <td> Whether to prompt user to kill broker before a commit batch.
+ * <tr><td> failAfterSend <td> false <td> Whether to prompt user to kill broker after a send.
+ * <tr><td> failBeforeSend <td> false <td> Whether to prompt user to kill broker before a send.
+ * <tr><td> failOnce <td> true <td> Whether to prompt for failover only once.
+ * <tr><td> username <td> guest <td> The username to access the broker with.
+ * <tr><td> password <td> guest <td> The password to access the broker with.
+ * <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
+ * <tr><td> destinationCount <td> 1 <td> The number of destinations to send pings to.
+ * <tr><td> numConsumers <td> 1 <td> The number of consumers on each destination.
+ * <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
+ * <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
+ * <tr><td> uniqueDests <td> true <td> Whether each receivers only listens to one ping destination or all.
+ * <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
+ * <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ * 0 - SESSION_TRANSACTED
+ * 1 - AUTO_ACKNOWLEDGE
+ * 2 - CLIENT_ACKNOWLEDGE
+ * 3 - DUPS_OK_ACKNOWLEDGE
+ * 257 - NO_ACKNOWLEDGE
+ * 258 - PRE_ACKNOWLEDGE
+ * <tr><td> consTransacted <td> false <td> Whether or not consumers use transactions. Defaults to the same value
+ * as the 'transacted' option if not seperately defined.
+ * <tr><td> consAckMode <td> AUTO_ACK <td> The message acknowledgement mode for consumers. Defaults to the same
+ * value as 'ackMode' if not seperately defined.
+ * <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
+ * Limits the volume of messages currently buffered on the client
+ * or broker. Can help scale test clients by limiting amount of buffered
+ * data to avoid out of memory errors.
+ * </table>
+ *
+ * <p/>This implements the Runnable interface with a run method that implements an infinite ping loop. The ping loop
+ * does all its work through helper methods, so that code wishing to run a ping-pong cycle is not forced to do so by
+ * starting a new thread. The command line invocation does take advantage of this ping loop. A shutdown hook is also
+ * registered to terminate the ping-pong loop cleanly.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a ping and wait for all responses cycle.
+ * <tr><td> Provide command line invocation to loop the ping cycle on a configurable broker url.
+ * </table>
+ *
+ * @todo Use read/write lock in the onmessage, not for reading writing but to make use of a shared and exlcusive lock pair.
+ * Obtain read lock on all messages, before decrementing the message count. At the end of the on message method add a
+ * block that obtains the write lock for the very last message, releases any waiting producer. Means that the last
+ * message waits until all other messages have been handled before releasing producers but allows messages to be
+ * processed concurrently, unlike the current synchronized block.
+ */
+public class PingPongProducer implements Runnable, ExceptionListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(PingPongProducer.class);
+
+ /** Holds the name of the property to determine whether of not client id is overridden at connection time. */
+ public static final String OVERRIDE_CLIENT_ID_PROPNAME = "overrideClientId";
+
+ /** Holds the default value of the override client id flag. */
+ public static final String OVERRIDE_CLIENT_ID_DEAFULT = "false";
+
+ /** Holds the name of the property to define the JNDI factory name with. */
+ public static final String FACTORY_NAME_PROPNAME = "factoryName";
+
+ /** Holds the default JNDI name of the connection factory. */
+ public static final String FACTORY_NAME_DEAFULT = "local";
+
+ /** Holds the name of the property to set the JNDI initial context properties with. */
+ public static final String FILE_PROPERTIES_PROPNAME = "properties";
+
+ /** Holds the default file name of the JNDI initial context properties. */
+ public static final String FILE_PROPERTIES_DEAFULT = "perftests.properties";
+
+ /** Holds the name of the property to get the test message size from. */
+ public static final String MESSAGE_SIZE_PROPNAME = "messageSize";
+
+ /** Used to set up a default message size. */
+ public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+ /** Holds the name of the property to get the ping queue name from. */
+ public static final String PING_QUEUE_NAME_PROPNAME = "destinationName";
+
+ /** Holds the name of the default destination to send pings on. */
+ public static final String PING_QUEUE_NAME_DEFAULT = "ping";
+
+ /** Holds the name of the property to get the queue name postfix from. */
+ public static final String QUEUE_NAME_POSTFIX_PROPNAME = "queueNamePostfix";
+
+ /** Holds the default queue name postfix value. */
+ public static final String QUEUE_NAME_POSTFIX_DEFAULT = "";
+
+ /** Holds the name of the property to get the test delivery mode from. */
+ public static final String PERSISTENT_MODE_PROPNAME = "persistent";
+
+ /** Holds the message delivery mode to use for the test. */
+ public static final boolean PERSISTENT_MODE_DEFAULT = false;
+
+ /** Holds the name of the property to get the test transactional mode from. */
+ public static final String TRANSACTED_PROPNAME = "transacted";
+
+ /** Holds the transactional mode to use for the test. */
+ public static final boolean TRANSACTED_DEFAULT = false;
+
+ /** Holds the name of the property to get the test consumer transacted mode from. */
+ public static final String CONSUMER_TRANSACTED_PROPNAME = "consTransacted";
+
+ /** Holds the consumer transactional mode default setting. */
+ public static final boolean CONSUMER_TRANSACTED_DEFAULT = false;
+
+ /** Holds the name of the property to get the test broker url from. */
+ public static final String BROKER_PROPNAME = "broker";
+
+ /** Holds the default broker url for the test. */
+ public static final String BROKER_DEFAULT = "tcp://localhost:5672";
+
+ /** Holds the name of the property to get the test broker virtual path. */
+ public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+ /** Holds the default virtual path for the test. */
+ public static final String VIRTUAL_HOST_DEFAULT = "";
+
+ /** Holds the name of the property to get the message rate from. */
+ public static final String RATE_PROPNAME = "rate";
+
+ /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
+ public static final int RATE_DEFAULT = 0;
+
+ /** Holds the name of the property to get the verbose mode proeprty from. */
+ public static final String VERBOSE_PROPNAME = "verbose";
+
+ /** Holds the default verbose mode. */
+ public static final boolean VERBOSE_DEFAULT = false;
+
+ /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */
+ public static final String PUBSUB_PROPNAME = "pubsub";
+
+ /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
+ public static final boolean PUBSUB_DEFAULT = false;
+
+ /** Holds the name of the property to get the fail after commit flag from. */
+ public static final String FAIL_AFTER_COMMIT_PROPNAME = "failAfterCommit";
+
+ /** Holds the default failover after commit test flag. */
+ public static final boolean FAIL_AFTER_COMMIT_DEFAULT = false;
+
+ /** Holds the name of the proeprty to get the fail before commit flag from. */
+ public static final String FAIL_BEFORE_COMMIT_PROPNAME = "failBeforeCommit";
+
+ /** Holds the default failover before commit test flag. */
+ public static final boolean FAIL_BEFORE_COMMIT_DEFAULT = false;
+
+ /** Holds the name of the proeprty to get the fail after send flag from. */
+ public static final String FAIL_AFTER_SEND_PROPNAME = "failAfterSend";
+
+ /** Holds the default failover after send test flag. */
+ public static final boolean FAIL_AFTER_SEND_DEFAULT = false;
+
+ /** Holds the name of the property to get the fail before send flag from. */
+ public static final String FAIL_BEFORE_SEND_PROPNAME = "failBeforeSend";
+
+ /** Holds the default failover before send test flag. */
+ public static final boolean FAIL_BEFORE_SEND_DEFAULT = false;
+
+ /** Holds the name of the property to get the fail once flag from. */
+ public static final String FAIL_ONCE_PROPNAME = "failOnce";
+
+ /** The default failover once flag, true means only do one failover, false means failover on every commit cycle. */
+ public static final boolean FAIL_ONCE_DEFAULT = true;
+
+ /** Holds the name of the property to get the broker access username from. */
+ public static final String USERNAME_PROPNAME = "username";
+
+ /** Holds the default broker log on username. */
+ public static final String USERNAME_DEFAULT = "guest";
+
+ /** Holds the name of the property to get the broker access password from. */
+ public static final String PASSWORD_PROPNAME = "password";
+
+ /** Holds the default broker log on password. */
+ public static final String PASSWORD_DEFAULT = "guest";
+
+ /** Holds the name of the proeprty to get the. */
+ public static final String SELECTOR_PROPNAME = "selector";
+
+ /** Holds the default message selector. */
+ public static final String SELECTOR_DEFAULT = "";
+
+ /** Holds the name of the property to get the destination count from. */
+ public static final String DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+ /** Defines the default number of destinations to ping. */
+ public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+ /** Holds the name of the property to get the number of consumers per destination from. */
+ public static final String NUM_CONSUMERS_PROPNAME = "numConsumers";
+
+ /** Defines the default number consumers per destination. */
+ public static final int NUM_CONSUMERS_DEFAULT = 1;
+
+ /** Holds the name of the property to get the waiting timeout for response messages. */
+ public static final String TIMEOUT_PROPNAME = "timeout";
+
+ /** Default time to wait before assuming that a ping has timed out. */
+ public static final long TIMEOUT_DEFAULT = 30000;
+
+ /** Holds the name of the property to get the commit batch size from. */
+ public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+ /** Defines the default number of pings to send in each transaction when running transactionally. */
+ public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+ /** Holds the name of the property to get the unique destinations flag from. */
+ public static final String UNIQUE_DESTS_PROPNAME = "uniqueDests";
+
+ /** Defines the default value for the unique destinations property. */
+ public static final boolean UNIQUE_DESTS_DEFAULT = true;
+
+ /** Holds the name of the property to get the durable destinations flag from. */
+ public static final String DURABLE_DESTS_PROPNAME = "durableDests";
+
+ /** Defines the default value of the durable destinations flag. */
+ public static final boolean DURABLE_DESTS_DEFAULT = false;
+
+ /** Holds the name of the proeprty to get the message acknowledgement mode from. */
+ public static final String ACK_MODE_PROPNAME = "ackMode";
+
+ /** Defines the default message acknowledgement mode. */
+ public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /** Holds the name of the property to get the consumers message acknowledgement mode from. */
+ public static final String CONSUMER_ACK_MODE_PROPNAME = "consAckMode";
+
+ /** Defines the default consumers message acknowledgement mode. */
+ public static final int CONSUMER_ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /** Holds the name of the property to get the maximum pending message size setting from. */
+ public static final String MAX_PENDING_PROPNAME = "maxPending";
+
+ /** Defines the default value for the maximum pending message size setting. 0 means no limit. */
+ public static final int MAX_PENDING_DEFAULT = 0;
+
+ /** Defines the default prefetch size to use when consuming messages. */
+ public static final int PREFETCH_DEFAULT = 100;
+
+ /** Defines the default value of the no local flag to use when consuming messages. */
+ public static final boolean NO_LOCAL_DEFAULT = false;
+
+ /** Defines the default value of the exclusive flag to use when consuming messages. */
+ public static final boolean EXCLUSIVE_DEFAULT = false;
+
+ /** Holds the name of the property to store nanosecond timestamps in ping messages with. */
+ public static final String MESSAGE_TIMESTAMP_PROPNAME = "timestamp";
+
+ /** Holds the default configuration properties. */
+ public static ParsedProperties defaults = new ParsedProperties();
+
+ static
+ {
+ defaults.setPropertyIfNull(OVERRIDE_CLIENT_ID_PROPNAME, OVERRIDE_CLIENT_ID_DEAFULT);
+ defaults.setPropertyIfNull(FILE_PROPERTIES_PROPNAME, FILE_PROPERTIES_DEAFULT);
+ defaults.setPropertyIfNull(FACTORY_NAME_PROPNAME, FACTORY_NAME_DEAFULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(PING_QUEUE_NAME_PROPNAME, PING_QUEUE_NAME_DEFAULT);
+ defaults.setPropertyIfNull(QUEUE_NAME_POSTFIX_PROPNAME, QUEUE_NAME_POSTFIX_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
+ defaults.setPropertyIfNull(CONSUMER_TRANSACTED_PROPNAME, CONSUMER_TRANSACTED_DEFAULT);
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(CONSUMER_ACK_MODE_PROPNAME, CONSUMER_ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+ defaults.setPropertyIfNull(UNIQUE_DESTS_PROPNAME, UNIQUE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(FAIL_BEFORE_COMMIT_PROPNAME, FAIL_BEFORE_COMMIT_DEFAULT);
+ defaults.setPropertyIfNull(FAIL_AFTER_COMMIT_PROPNAME, FAIL_AFTER_COMMIT_DEFAULT);
+ defaults.setPropertyIfNull(FAIL_BEFORE_SEND_PROPNAME, FAIL_BEFORE_SEND_DEFAULT);
+ defaults.setPropertyIfNull(FAIL_AFTER_SEND_PROPNAME, FAIL_AFTER_SEND_DEFAULT);
+ defaults.setPropertyIfNull(FAIL_ONCE_PROPNAME, FAIL_ONCE_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
+ defaults.setPropertyIfNull(NUM_CONSUMERS_PROPNAME, NUM_CONSUMERS_DEFAULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ }
+
+ /** Allows setting of client ID on the connection, rather than through the connection URL. */
+ protected boolean _overrideClientId;
+
+ /** Holds the JNDI name of the JMS connection factory. */
+ protected String _factoryName;
+
+ /** Holds the name of the properties file to configure JNDI with. */
+ protected String _fileProperties;
+
+ /** Holds the broker url. */
+ protected String _brokerDetails;
+
+ /** Holds the username to access the broker with. */
+ protected String _username;
+
+ /** Holds the password to access the broker with. */
+ protected String _password;
+
+ /** Holds the virtual host on the broker to run the tests through. */
+ protected String _virtualpath;
+
+ /** Holds the root name from which to generate test destination names. */
+ protected String _destinationName;
+
+ /** Holds the default queue name postfix value. */
+ protected String _queueNamePostfix;
+
+ /** Holds the message selector to filter the pings with. */
+ protected String _selector;
+
+ /** Holds the producers transactional mode flag. */
+ protected boolean _transacted;
+
+ /** Holds the consumers transactional mode flag. */
+ protected boolean _consTransacted;
+
+ /** Determines whether this producer sends persistent messages. */
+ protected boolean _persistent;
+
+ /** Holds the acknowledgement mode used for the producers. */
+ protected int _ackMode;
+
+ /** Holds the acknowledgement mode setting for the consumers. */
+ protected int _consAckMode;
+
+ /** Determines what size of messages this producer sends. */
+ protected int _messageSize;
+
+ /** Used to indicate that the ping loop should print out whenever it pings. */
+ protected boolean _verbose;
+
+ /** Flag used to indicate if this is a point to point or pub/sub ping client. */
+ protected boolean _isPubSub;
+
+ /** Flag used to indicate if the destinations should be unique client. */
+ protected boolean _isUnique;
+
+ /** Flag used to indicate that durable destination should be used. */
+ protected boolean _isDurable;
+
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a commit. */
+ protected boolean _failBeforeCommit;
+
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a commit. */
+ protected boolean _failAfterCommit;
+
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover before a send. */
+ protected boolean _failBeforeSend;
+
+ /** Flag used to indicate that the user should be prompted to terminate a broker, to test failover after a send. */
+ protected boolean _failAfterSend;
+
+ /** Flag used to indicate that failover prompting should only be done on the first commit, not on every commit. */
+ protected boolean _failOnce;
+
+ /** Holds the number of sends that should be performed in every transaction when using transactions. */
+ protected int _txBatchSize;
+
+ /** Holds the number of destinations to ping. */
+ protected int _noOfDestinations;
+
+ /** Holds the number of consumers per destination. */
+ protected int _noOfConsumers;
+
+ /** Holds the maximum send rate in herz. */
+ protected int _rate;
+
+ /**
+ * Holds the size of the maximum amount of pending data that the client should buffer, sending is suspended
+ * if this limit is breached.
+ */
+ protected int _maxPendingSize;
+
+ /** A source for providing sequential unique correlation ids. These will be unique within the same JVM. */
+ private static AtomicLong _correlationIdGenerator = new AtomicLong(0L);
+
+ /** A source for providing sequential unqiue ids for instances of this class to be identifed with. */
+ private static AtomicInteger _instanceIdGenerator = new AtomicInteger(0);
+
+ /** Holds this instances unique id. */
+ private int instanceId;
+
+ /**
+ * Holds a map from message ids to latches on which threads wait for replies. This map is shared accross multiple
+ * ping producers on the same JVM.
+ */
+ private static Map<String, PerCorrelationId> perCorrelationIds =
+ Collections.synchronizedMap(new HashMap<String, PerCorrelationId>());
+
+ /** A convenient formatter to use when time stamping output. */
+ protected static final DateFormat timestampFormatter = new SimpleDateFormat("hh:mm:ss:SS");
+
+ /** Holds the connection for the message producer. */
+ protected Connection _connection;
+
+ /** Holds the consumer connections. */
+ protected Connection[] _consumerConnection;
+
+ /** Holds the controlSession on which ping replies are received. */
+ protected Session[] _consumerSession;
+
+ /** Holds the producer controlSession, needed to create ping messages. */
+ protected Session _producerSession;
+
+ /** Holds the destination where the response messages will arrive. */
+ protected Destination _replyDestination;
+
+ /** Holds the set of destinations that this ping producer pings. */
+ protected List<Destination> _pingDestinations;
+
+ /** Used to restrict the sending rate to a specified limit. */
+ protected Throttle _rateLimiter;
+
+ /** Holds a message listener that this message listener chains all its messages to. */
+ protected ChainedMessageListener _chainedMessageListener = null;
+
+ /**
+ * This id generator is used to generate ids to append to the queue name to ensure that queues can be unique when
+ * creating multiple ping producers in the same JVM.
+ */
+ protected static AtomicInteger _queueJVMSequenceID = new AtomicInteger();
+
+ /**
+ * This id generator is used to generates ids that are only unique within this pinger. Creating multiple pingers
+ * on the same JVM using this id generator will allow them to ping on the same queues.
+ */
+ protected AtomicInteger _queueSharedID = new AtomicInteger();
+
+ /** Used to tell the ping loop when to terminate, it only runs while this is true. */
+ protected boolean _publish = true;
+
+ /** Holds the message producer to send the pings through. */
+ protected MessageProducer _producer;
+
+ /** Holds the message consumer to receive the ping replies through. */
+ protected MessageConsumer[] _consumer;
+
+ /** The prompt to display when asking the user to kill the broker for failover testing. */
+ private static final String KILL_BROKER_PROMPT = "Kill broker now, then press Return.";
+
+ /** Holds the name for this test client to be identified to the broker with. */
+ private String _clientID;
+
+ /** Keeps count of the total messages sent purely for debugging purposes. */
+ private static AtomicInteger numSent = new AtomicInteger();
+
+ /**
+ * Holds a monitor which is used to synchronize sender and receivers threads, where the sender has elected
+ * to wait until the number of unreceived message is reduced before continuing to send. This monitor is a
+ * fair SynchronousQueue becuase that provides fair scheduling, to ensure that all producer threads get an
+ * equal chance to produce messages.
+ */
+ static final SynchronousQueue _sendPauseMonitor = new SynchronousQueue(true);
+
+ /** Keeps a count of the number of message currently sent but not received. */
+ static AtomicInteger _unreceived = new AtomicInteger(0);
+
+ /**
+ * Creates a ping producer with the specified parameters, of which there are many. See the class level comments
+ * for details. This constructor creates a connection to the broker and creates producer and consumer sessions on
+ * it, to send and recieve its pings and replies on.
+ *
+ * @param overrides Properties containing any desired overrides to the defaults.
+ *
+ * @throws Exception Any exceptions are allowed to fall through.
+ */
+ public PingPongProducer(Properties overrides) throws Exception
+ {
+ // log.debug("public PingPongProducer(Properties overrides = " + overrides + "): called");
+ instanceId = _instanceIdGenerator.getAndIncrement();
+
+ // Create a set of parsed properties from the defaults overriden by the passed in values.
+ ParsedProperties properties = new ParsedProperties(defaults);
+ properties.putAll(overrides);
+
+ // Extract the configuration properties to set the pinger up with.
+ _overrideClientId = properties.getPropertyAsBoolean(OVERRIDE_CLIENT_ID_PROPNAME);
+ _factoryName = properties.getProperty(FACTORY_NAME_PROPNAME);
+ _fileProperties = properties.getProperty(FILE_PROPERTIES_PROPNAME);
+ _brokerDetails = properties.getProperty(BROKER_PROPNAME);
+ _username = properties.getProperty(USERNAME_PROPNAME);
+ _password = properties.getProperty(PASSWORD_PROPNAME);
+ _virtualpath = properties.getProperty(VIRTUAL_HOST_PROPNAME);
+ _destinationName = properties.getProperty(PING_QUEUE_NAME_PROPNAME);
+ _queueNamePostfix = properties.getProperty(QUEUE_NAME_POSTFIX_PROPNAME);
+ _selector = properties.getProperty(SELECTOR_PROPNAME);
+ _transacted = properties.getPropertyAsBoolean(TRANSACTED_PROPNAME);
+ _consTransacted = properties.getPropertyAsBoolean(CONSUMER_TRANSACTED_PROPNAME);
+ _persistent = properties.getPropertyAsBoolean(PERSISTENT_MODE_PROPNAME);
+ _messageSize = properties.getPropertyAsInteger(MESSAGE_SIZE_PROPNAME);
+ _verbose = properties.getPropertyAsBoolean(VERBOSE_PROPNAME);
+ _failAfterCommit = properties.getPropertyAsBoolean(FAIL_AFTER_COMMIT_PROPNAME);
+ _failBeforeCommit = properties.getPropertyAsBoolean(FAIL_BEFORE_COMMIT_PROPNAME);
+ _failAfterSend = properties.getPropertyAsBoolean(FAIL_AFTER_SEND_PROPNAME);
+ _failBeforeSend = properties.getPropertyAsBoolean(FAIL_BEFORE_SEND_PROPNAME);
+ _failOnce = properties.getPropertyAsBoolean(FAIL_ONCE_PROPNAME);
+ _txBatchSize = properties.getPropertyAsInteger(TX_BATCH_SIZE_PROPNAME);
+ _noOfDestinations = properties.getPropertyAsInteger(DESTINATION_COUNT_PROPNAME);
+ _noOfConsumers = properties.getPropertyAsInteger(NUM_CONSUMERS_PROPNAME);
+ _rate = properties.getPropertyAsInteger(RATE_PROPNAME);
+ _isPubSub = properties.getPropertyAsBoolean(PUBSUB_PROPNAME);
+ _isUnique = properties.getPropertyAsBoolean(UNIQUE_DESTS_PROPNAME);
+ _isDurable = properties.getPropertyAsBoolean(DURABLE_DESTS_PROPNAME);
+ _ackMode = _transacted ? 0 : properties.getPropertyAsInteger(ACK_MODE_PROPNAME);
+ _consAckMode = _consTransacted ? 0 : properties.getPropertyAsInteger(CONSUMER_ACK_MODE_PROPNAME);
+ _maxPendingSize = properties.getPropertyAsInteger(MAX_PENDING_PROPNAME);
+
+ // Check that one or more destinations were specified.
+ if (_noOfDestinations < 1)
+ {
+ throw new IllegalArgumentException("There must be at least one destination.");
+ }
+
+ // Set up a throttle to control the send rate, if a rate > 0 is specified.
+ if (_rate > 0)
+ {
+ _rateLimiter = new BatchedThrottle();
+ _rateLimiter.setRate(_rate);
+ }
+
+ // Create the connection and message producers/consumers.
+ // establishConnection(true, true);
+ }
+
+ /**
+ * Establishes a connection to the broker and creates message consumers and producers based on the parameters
+ * that this ping client was created with.
+ *
+ * @param producer Flag to indicate whether or not the producer should be set up.
+ * @param consumer Flag to indicate whether or not the consumers should be set up.
+ *
+ * @throws Exception Any exceptions are allowed to fall through.
+ */
+ public void establishConnection(boolean producer, boolean consumer) throws Exception
+ {
+ // log.debug("public void establishConnection(): called");
+
+ // Generate a unique identifying name for this client, based on it ip address and the current time.
+ InetAddress address = InetAddress.getLocalHost();
+ // _clientID = address.getHostName() + System.currentTimeMillis();
+ _clientID = "perftest_" + instanceId;
+
+ // Create a connection to the broker.
+ createConnection(_clientID);
+
+ // Create transactional or non-transactional sessions, based on the command line arguments.
+ _producerSession = _connection.createSession(_transacted, _ackMode);
+
+ _consumerSession = new Session[_noOfConsumers];
+
+ for (int i = 0; i < _noOfConsumers; i++)
+ {
+ _consumerSession[i] = _consumerConnection[i].createSession(_consTransacted, _consAckMode);
+ }
+
+ // Create the destinations to send pings to and receive replies from.
+ _replyDestination = _consumerSession[0].createTemporaryQueue();
+ createPingDestinations(_noOfDestinations, _selector, _destinationName, _isUnique, _isDurable);
+
+ // Create the message producer only if instructed to.
+ if (producer)
+ {
+ createProducer();
+ }
+
+ // Create the message consumer only if instructed to.
+ if (consumer)
+ {
+ createReplyConsumers(getReplyDestinations(), _selector);
+ }
+ }
+
+ /**
+ * Establishes a connection to the broker, based on the configuration parameters that this ping client was
+ * created with.
+ *
+ * @param clientID The clients identifier.
+ *
+ * @throws JMSException Underlying exceptions allowed to fall through.
+ * @throws NamingException Underlying exceptions allowed to fall through.
+ * @throws IOException Underlying exceptions allowed to fall through.
+ */
+ protected void createConnection(String clientID) throws JMSException, NamingException, IOException
+ {
+ // _log.debug("protected void createConnection(String clientID = " + clientID + "): called");
+
+ // _log.debug("Creating a connection for the message producer.");
+ File propsFile = new File(_fileProperties);
+ InputStream is = new FileInputStream(propsFile);
+ Properties properties = new Properties();
+ properties.load(is);
+
+ Context context = new InitialContext(properties);
+ ConnectionFactory factory = (ConnectionFactory) context.lookup(_factoryName);
+ _connection = factory.createConnection(_username, _password);
+
+ if (_overrideClientId)
+ {
+ _connection.setClientID(clientID);
+ }
+
+ // _log.debug("Creating " + _noOfConsumers + " connections for the consumers.");
+
+ _consumerConnection = new Connection[_noOfConsumers];
+
+ for (int i = 0; i < _noOfConsumers; i++)
+ {
+ _consumerConnection[i] = factory.createConnection(_username, _password);
+ // _consumerConnection[i].setClientID(clientID);
+ }
+ }
+
+ /**
+ * Starts a ping-pong loop running from the command line. The bounce back client {@link PingPongBouncer} also needs
+ * to be started to bounce the pings back again.
+ *
+ * @param args The command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ try
+ {
+ Properties options =
+ CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][] {}), System.getProperties());
+
+ // Create a ping producer overriding its defaults with all options passed on the command line.
+ PingPongProducer pingProducer = new PingPongProducer(options);
+ pingProducer.establishConnection(true, true);
+
+ // Start the ping producers dispatch thread running.
+ pingProducer._connection.start();
+
+ // Create a shutdown hook to terminate the ping-pong producer.
+ Runtime.getRuntime().addShutdownHook(pingProducer.getShutdownHook());
+
+ // Ensure that the ping pong producer is registered to listen for exceptions on the connection too.
+ pingProducer._connection.setExceptionListener(pingProducer);
+
+ // Create the ping loop thread and run it until it is terminated by the shutdown hook or exception.
+ Thread pingThread = new Thread(pingProducer);
+ pingThread.run();
+ pingThread.join();
+ }
+ catch (Exception e)
+ {
+ System.err.println(e.getMessage());
+ log.error("Top level handler caught execption.", e);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Convenience method for a short pause.
+ *
+ * @param sleepTime The time in milliseconds to pause for.
+ */
+ public static void pause(long sleepTime)
+ {
+ if (sleepTime > 0)
+ {
+ try
+ {
+ Thread.sleep(sleepTime);
+ }
+ catch (InterruptedException ie)
+ { }
+ }
+ }
+
+ /**
+ * Gets all the reply destinations (to listen for replies on). In this case this will just be the single reply to
+ * destination of this pinger.
+ *
+ * @return The single reply to destination of this pinger, wrapped in a list.
+ */
+ public List<Destination> getReplyDestinations()
+ {
+ // log.debug("public List<Destination> getReplyDestinations(): called");
+
+ List<Destination> replyDestinations = new ArrayList<Destination>();
+ replyDestinations.add(_replyDestination);
+
+ // log.debug("replyDestinations = " + replyDestinations);
+
+ return replyDestinations;
+ }
+
+ /**
+ * Creates the producer to send the pings on. This is created without a default destination. Its persistent delivery
+ * flag is set accoring the ping producer creation options.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createProducer() throws JMSException
+ {
+ // log.debug("public void createProducer(): called");
+
+ _producer = (MessageProducer) _producerSession.createProducer(null);
+ _producer.setDeliveryMode(_persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
+
+ // log.debug("Created producer for " + (_persistent ? "persistent" : "non-persistent") + " messages.");
+ }
+
+ /**
+ * Creates consumers for the specified number of destinations. The destinations themselves are also created by this
+ * method.
+ *
+ * @param noOfDestinations The number of destinations to create consumers for.
+ * @param selector The message selector to filter the consumers with.
+ * @param rootName The root of the name, or actual name if only one is being created.
+ * @param unique <tt>true</tt> to make the destinations unique to this pinger, <tt>false</tt> to share the
+ * numbering with all pingers on the same JVM.
+ * @param durable If the destinations are durable topics.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createPingDestinations(int noOfDestinations, String selector, String rootName, boolean unique,
+ boolean durable) throws JMSException
+ {
+ /*log.debug("public void createPingDestinations(int noOfDestinations = " + noOfDestinations + ", String selector = "
+ + selector + ", String rootName = " + rootName + ", boolean unique = " + unique + ", boolean durable = "
+ + durable + "): called");*/
+
+ _pingDestinations = new ArrayList<Destination>();
+
+ // Create the desired number of ping destinations and consumers for them.
+ // log.debug("Creating " + noOfDestinations + " destinations to ping.");
+
+ for (int i = 0; i < noOfDestinations; i++)
+ {
+ Destination destination;
+ String id;
+
+ // Generate an id, unique within this pinger or to the whole JVM depending on the unique flag.
+ if (unique)
+ {
+ // log.debug("Creating unique destinations.");
+ id = "_" + _queueJVMSequenceID.incrementAndGet() + "_" + _connection.getClientID();
+ }
+ else
+ {
+ // log.debug("Creating shared destinations.");
+ id = "_" + _queueSharedID.incrementAndGet();
+ }
+
+ // Check if this is a pub/sub pinger, in which case create topics.
+ if (_isPubSub)
+ {
+ destination = _producerSession.createTopic(rootName + id);
+ // log.debug("Created non-durable topic " + destination);
+
+ if (durable)
+ {
+ _producerSession.createDurableSubscriber((Topic) destination, _connection.getClientID());
+ }
+ }
+ // Otherwise this is a p2p pinger, in which case create queues.
+ else
+ {
+ destination = _producerSession.createQueue(rootName + id + _queueNamePostfix);
+ // log.debug("Created queue " + destination);
+ }
+
+ // Keep the destination.
+ _pingDestinations.add(destination);
+ }
+ }
+
+ /**
+ * Creates consumers for the specified destinations and registers this pinger to listen to their messages.
+ *
+ * @param destinations The destinations to listen to.
+ * @param selector A selector to filter the messages with.
+ *
+ * @throws javax.jms.JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void createReplyConsumers(Collection<Destination> destinations, String selector) throws JMSException
+ {
+ /*log.debug("public void createReplyConsumers(Collection<Destination> destinations = " + destinations
+ + ", String selector = " + selector + "): called");*/
+
+ log.debug("There are " + destinations.size() + " destinations.");
+ log.debug("Creating " + _noOfConsumers + " consumers on each destination.");
+ log.debug("Total number of consumers is: " + (destinations.size() * _noOfConsumers));
+
+ for (Destination destination : destinations)
+ {
+ _consumer = new MessageConsumer[_noOfConsumers];
+
+ for (int i = 0; i < _noOfConsumers; i++)
+ {
+ // Create a consumer for the destination and set this pinger to listen to its messages.
+ _consumer[i] = _consumerSession[i].createConsumer(destination, selector, NO_LOCAL_DEFAULT);
+
+ final int consumerNo = i;
+
+ _consumer[i].setMessageListener(new MessageListener()
+ {
+ public void onMessage(Message message)
+ {
+ onMessageWithConsumerNo(message, consumerNo);
+ }
+ });
+
+ log.debug("Set consumer " + i + " to listen to replies sent to destination: " + destination);
+ }
+ }
+ }
+
+ /**
+ * Stores the received message in the replies map, then resets the boolean latch that a thread waiting for a
+ * correlating reply may be waiting on. This is only done if the reply has a correlation id that is expected in the
+ * replies map.
+ *
+ * @param message The received message.
+ * @param consumerNo The consumer number within this test pinger instance.
+ */
+ public void onMessageWithConsumerNo(Message message, int consumerNo)
+ {
+ // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo = " + consumerNo + "): called");
+ try
+ {
+ long now = System.nanoTime();
+ long timestamp = getTimestamp(message);
+ long pingTime = now - timestamp;
+
+ // NDC.push("id" + instanceId + "/cons" + consumerNo);
+
+ // Extract the messages correlation id.
+ String correlationID = message.getJMSCorrelationID();
+ // log.debug("correlationID = " + correlationID);
+
+ // int num = message.getIntProperty("MSG_NUM");
+ // log.info("Message " + num + " received.");
+
+ boolean isRedelivered = message.getJMSRedelivered();
+ // log.debug("isRedelivered = " + isRedelivered);
+
+ if (!isRedelivered)
+ {
+ // Countdown on the traffic light if there is one for the matching correlation id.
+ PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID);
+
+ if (perCorrelationId != null)
+ {
+ CountDownLatch trafficLight = perCorrelationId.trafficLight;
+
+ // Restart the timeout timer on every message.
+ perCorrelationId.timeOutStart = System.nanoTime();
+
+ // log.debug("Reply was expected, decrementing the latch for the id, " + correlationID);
+
+ // Release waiting senders if there are some and using maxPending limit.
+ if ((_maxPendingSize > 0))
+ {
+ // Decrement the count of sent but not yet received messages.
+ int unreceived = _unreceived.decrementAndGet();
+ int unreceivedSize =
+ (unreceived * ((_messageSize == 0) ? 1 : _messageSize))
+ / (_isPubSub ? getConsumersPerDestination() : 1);
+
+ // log.debug("unreceived = " + unreceived);
+ // log.debug("unreceivedSize = " + unreceivedSize);
+
+ // synchronized (_sendPauseMonitor)
+ // {
+ if (unreceivedSize < _maxPendingSize)
+ {
+ _sendPauseMonitor.poll();
+ }
+ // }
+ }
+
+ // Decrement the countdown latch. Before this point, it is possible that two threads might enter this
+ // method simultanesouly with the same correlation id. Decrementing the latch in a synchronized block
+ // ensures that each thread will get a unique value for the remaining messages.
+ long trueCount;
+ long remainingCount;
+
+ synchronized (trafficLight)
+ {
+ trafficLight.countDown();
+
+ trueCount = trafficLight.getCount();
+ remainingCount = trueCount - 1;
+
+ // NDC.push("/rem" + remainingCount);
+
+ // log.debug("remainingCount = " + remainingCount);
+ // log.debug("trueCount = " + trueCount);
+
+ // Commit on transaction batch size boundaries. At this point in time the waiting producer
+ // remains blocked, even on the last message.
+ // Commit count is divided by noOfConsumers in p2p mode, so that each consumer only commits on
+ // each batch boundary. For pub/sub each consumer gets every message so no division is done.
+ // When running in client ack mode, an ack is done instead of a commit, on the commit batch
+ // size boundaries.
+ long commitCount = _isPubSub ? remainingCount : (remainingCount / _noOfConsumers);
+ // log.debug("commitCount = " + commitCount);
+
+ if ((commitCount % _txBatchSize) == 0)
+ {
+ if (_consAckMode == 2)
+ {
+ // log.debug("Doing client ack for consumer " + consumerNo + ".");
+ message.acknowledge();
+ }
+ else
+ {
+ // log.debug("Trying commit for consumer " + consumerNo + ".");
+ commitTx(_consumerSession[consumerNo]);
+ // log.info("Tx committed on consumer " + consumerNo);
+ }
+ }
+
+ // Forward the message and remaining count to any interested chained message listener.
+ if (_chainedMessageListener != null)
+ {
+ _chainedMessageListener.onMessage(message, (int) remainingCount, pingTime);
+ }
+
+ // Check if this is the last message, in which case release any waiting producers. This is done
+ // after the transaction has been committed and any listeners notified.
+ if (trueCount == 1)
+ {
+ trafficLight.countDown();
+ }
+ }
+ }
+ else
+ {
+ log.warn("Got unexpected message with correlationId: " + correlationID);
+ }
+ }
+ else
+ {
+ log.warn("Got redelivered message, ignoring.");
+ }
+ }
+ catch (JMSException e)
+ {
+ log.warn("There was a JMSException: " + e.getMessage(), e);
+ }
+ finally
+ {
+ // log.debug("public void onMessageWithConsumerNo(Message message, int consumerNo): ending");
+ // NDC.clear();
+ }
+ }
+
+ /**
+ * Sends the specified number of ping message and then waits for all correlating replies. If the wait times out
+ * before a reply arrives, then a null reply is returned from this method. This method allows the caller to specify
+ * the correlation id.
+ *
+ * @param message The message to send. If this is null, one is generated.
+ * @param numPings The number of ping messages to send.
+ * @param timeout The timeout in milliseconds.
+ * @param messageCorrelationId The message correlation id. If this is null, one is generated.
+ *
+ * @return The number of replies received. This may be less than the number sent if the timeout terminated the wait
+ * for all prematurely.
+ *
+ * @throws JMSException All underlying JMSExceptions are allowed to fall through.
+ * @throws InterruptedException When interrupted by a timeout
+ */
+ public int pingAndWaitForReply(Message message, int numPings, long timeout, String messageCorrelationId)
+ throws JMSException, InterruptedException
+ {
+ /*log.debug("public int pingAndWaitForReply(Message message, int numPings = " + numPings + ", long timeout = "
+ + timeout + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/
+
+ // Generate a unique correlation id to put on the messages before sending them, if one was not specified.
+ if (messageCorrelationId == null)
+ {
+ messageCorrelationId = Long.toString(_correlationIdGenerator.incrementAndGet());
+ }
+
+ try
+ {
+ // NDC.push("prod");
+
+ // Create a count down latch to count the number of replies with. This is created before the messages are
+ // sent so that the replies cannot be received before the count down is created.
+ // One is added to this, so that the last reply becomes a special case. The special case is that the
+ // chained message listener must be called before this sender can be unblocked, but that decrementing the
+ // countdown needs to be done before the chained listener can be called.
+ PerCorrelationId perCorrelationId = new PerCorrelationId();
+
+ perCorrelationId.trafficLight = new CountDownLatch(getExpectedNumPings(numPings) + 1);
+ perCorrelationIds.put(messageCorrelationId, perCorrelationId);
+
+ // Set up the current time as the start time for pinging on the correlation id. This is used to determine
+ // timeouts.
+ perCorrelationId.timeOutStart = System.nanoTime();
+
+ // Send the specifed number of messages.
+ pingNoWaitForReply(message, numPings, messageCorrelationId);
+
+ boolean timedOut;
+ boolean allMessagesReceived;
+ int numReplies;
+
+ do
+ {
+ // Block the current thread until replies to all the messages are received, or it times out.
+ perCorrelationId.trafficLight.await(timeout, TimeUnit.MILLISECONDS);
+
+ // Work out how many replies were receieved.
+ numReplies = getExpectedNumPings(numPings) - (int) perCorrelationId.trafficLight.getCount();
+
+ allMessagesReceived = numReplies == getExpectedNumPings(numPings);
+
+ // log.debug("numReplies = " + numReplies);
+ // log.debug("allMessagesReceived = " + allMessagesReceived);
+
+ // Recheck the timeout condition.
+ long now = System.nanoTime();
+ long lastMessageReceievedAt = perCorrelationId.timeOutStart;
+ timedOut = (now - lastMessageReceievedAt) > (timeout * 1000000);
+
+ // log.debug("now = " + now);
+ // log.debug("lastMessageReceievedAt = " + lastMessageReceievedAt);
+ }
+ while (!timedOut && !allMessagesReceived);
+
+ if ((numReplies < getExpectedNumPings(numPings)) && _verbose)
+ {
+ log.info("Timed out (" + timeout + " ms) before all replies received on id, " + messageCorrelationId);
+ }
+ else if (_verbose)
+ {
+ log.info("Got all replies on id, " + messageCorrelationId);
+ }
+
+ // commitTx(_consumerSession);
+
+ // log.debug("public int pingAndWaitForReply(Message message, int numPings, long timeout): ending");
+
+ return numReplies;
+ }
+ // Ensure that the message countdown latch is always removed from the reply map. The reply map is long lived,
+ // so will be a memory leak if this is not done.
+ finally
+ {
+ // NDC.pop();
+ perCorrelationIds.remove(messageCorrelationId);
+ }
+ }
+
+ /**
+ * Sends the specified number of ping messages and does not wait for correlating replies.
+ *
+ * @param message The message to send.
+ * @param numPings The number of pings to send.
+ * @param messageCorrelationId A correlation id to place on all messages sent.
+ *
+ * @throws JMSException All underlying JMSExceptions are allowed to fall through.
+ */
+ public void pingNoWaitForReply(Message message, int numPings, String messageCorrelationId) throws JMSException
+ {
+ /*log.debug("public void pingNoWaitForReply(Message message, int numPings = " + numPings
+ + ", String messageCorrelationId = " + messageCorrelationId + "): called");*/
+
+ if (message == null)
+ {
+ message = getTestMessage(getReplyDestinations().get(0), _messageSize, _persistent);
+ }
+
+ message.setJMSCorrelationID(messageCorrelationId);
+
+ // Set up a committed flag to detect uncommitted messages at the end of the send loop. This may occurr if the
+ // transaction batch size is not a factor of the number of pings. In which case an extra commit at the end is
+ // needed.
+ boolean committed = false;
+
+ // Send all of the ping messages.
+ for (int i = 0; i < numPings; i++)
+ {
+ // Re-timestamp the message.
+ // message.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
+
+ // Send the message, passing in the message count.
+ committed = sendMessage(i, message);
+
+ // Spew out per message timings on every message sonly in verbose mode.
+ /*if (_verbose)
+ {
+ log.info(timestampFormatter.format(new Date()) + ": Pinged at with correlation id, " + messageCorrelationId);
+ }*/
+ }
+
+ // Call commit if the send loop finished before reaching a batch size boundary so there may still be uncommitted messages.
+ if (!committed)
+ {
+ commitTx(_producerSession);
+ }
+ }
+
+ /**
+ * Sends the sepcified message, applies rate limiting and possibly commits the current transaction. The count of
+ * messages sent so far must be specified and is used to round robin the ping destinations (where there are more
+ * than one), and to determine if the transaction batch size has been reached and the sent messages should be
+ * committed.
+ *
+ * @param i The count of messages sent so far in a loop of multiple calls to this send method.
+ * @param message The message to send.
+ *
+ * @return <tt>true</tt> if the messages were committed, <tt>false</tt> otherwise.
+ *
+ * @throws JMSException All underlyiung JMSExceptions are allowed to fall through.
+ */
+ protected boolean sendMessage(int i, Message message) throws JMSException
+ {
+ try
+ {
+ NDC.push("id" + instanceId + "/prod");
+
+ // log.debug("protected boolean sendMessage(int i = " + i + ", Message message): called");
+ // log.debug("_txBatchSize = " + _txBatchSize);
+
+ // Round robin the destinations as the messages are sent.
+ Destination destination = _pingDestinations.get(i % _pingDestinations.size());
+
+ // Prompt the user to kill the broker when doing failover testing.
+ _failBeforeSend = waitForUserToPromptOnFailure(_failBeforeSend);
+
+ // Get the test setup for the correlation id.
+ String correlationID = message.getJMSCorrelationID();
+ PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID);
+
+ // If necessary, wait until the max pending message size comes within its limit.
+ if (_maxPendingSize > 0)
+ {
+ synchronized (_sendPauseMonitor)
+ {
+ // Used to keep track of the number of times that send has to wait.
+ int numWaits = 0;
+
+ // The maximum number of waits before the test gives up and fails. This has been chosen to correspond with
+ // the test timeout.
+ int waitLimit = (int) (TIMEOUT_DEFAULT / 10000);
+
+ while (true)
+ {
+ // Get the size estimate of sent but not yet received messages.
+ int unreceived = _unreceived.get();
+ int unreceivedSize =
+ (unreceived * ((_messageSize == 0) ? 1 : _messageSize))
+ / (_isPubSub ? getConsumersPerDestination() : 1);
+
+ // log.debug("unreceived = " + unreceived);
+ // log.debug("unreceivedSize = " + unreceivedSize);
+ // log.debug("_maxPendingSize = " + _maxPendingSize);
+
+ if (unreceivedSize > _maxPendingSize)
+ {
+ // log.debug("unreceived size estimate over limit = " + unreceivedSize);
+
+ // Fail the test if the send has had to wait more than the maximum allowed number of times.
+ if (numWaits > waitLimit)
+ {
+ String errorMessage =
+ "Send has had to wait for the unreceivedSize (" + unreceivedSize
+ + ") to come below the maxPendingSize (" + _maxPendingSize + ") more that " + waitLimit
+ + " times.";
+ log.warn(errorMessage);
+ throw new RuntimeException(errorMessage);
+ }
+
+ // Wait on the send pause barrier for the limit to be re-established.
+ try
+ {
+ long start = System.nanoTime();
+ // _sendPauseMonitor.wait(10000);
+ _sendPauseMonitor.offer(new Object(), 10000, TimeUnit.MILLISECONDS);
+ long end = System.nanoTime();
+
+ // Count the wait only if it was for > 99% of the requested wait time.
+ if (((float) (end - start) / (float) (10000 * 1000000L)) > 0.99)
+ {
+ numWaits++;
+ }
+ }
+ catch (InterruptedException e)
+ {
+ // Restore the interrupted status
+ Thread.currentThread().interrupt();
+ throw new RuntimeException(e);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Send the message either to its round robin destination, or its default destination.
+ // int num = numSent.incrementAndGet();
+ // message.setIntProperty("MSG_NUM", num);
+ setTimestamp(message);
+
+ if (destination == null)
+ {
+ _producer.send(message);
+ }
+ else
+ {
+ _producer.send(destination, message);
+ }
+
+ // Increase the unreceived size, this may actually happen after the message is received.
+ // The unreceived size is incremented by the number of consumers that will get a copy of the message,
+ // in pub/sub mode.
+ if (_maxPendingSize > 0)
+ {
+ int newUnreceivedCount = _unreceived.addAndGet(_isPubSub ? getConsumersPerDestination() : 1);
+ // log.debug("newUnreceivedCount = " + newUnreceivedCount);
+ }
+
+ // Apply message rate throttling if a rate limit has been set up.
+ if (_rateLimiter != null)
+ {
+ _rateLimiter.throttle();
+ }
+
+ // Call commit every time the commit batch size is reached.
+ boolean committed = false;
+
+ // Commit on every transaction batch size boundary. Here i + 1 is the count of actual messages sent.
+ if (((i + 1) % _txBatchSize) == 0)
+ {
+ // log.debug("Trying commit on producer session.");
+ committed = commitTx(_producerSession);
+ }
+
+ return committed;
+ }
+ finally
+ {
+ NDC.clear();
+ }
+ }
+
+ /**
+ * If the specified fail flag is set, this method waits for the user to cause a failure and then indicate to the
+ * test that the failure has occurred, before the method returns.
+ *
+ * @param failFlag The fail flag to test.
+ *
+ * @return The new value for the fail flag. If the {@link #_failOnce} flag is set, then each fail flag is only
+ * used once, then reset.
+ */
+ private boolean waitForUserToPromptOnFailure(boolean failFlag)
+ {
+ if (failFlag)
+ {
+ if (_failOnce)
+ {
+ failFlag = false;
+ }
+
+ // log.debug("Failing Before Send");
+ waitForUser(KILL_BROKER_PROMPT);
+ }
+
+ return failFlag;
+ }
+
+ /**
+ * Implements a single iteration of the ping loop. This sends the number of pings specified by the transaction batch
+ * size property, and waits for replies to all of them. Any errors cause the publish flag to be cleared, which will
+ * terminate the pinger.
+ */
+ public void pingLoop()
+ {
+ try
+ {
+ // Generate a sample message and time stamp it.
+ Message msg = getTestMessage(_replyDestination, _messageSize, _persistent);
+ // setTimestamp(msg);
+
+ // Send the message and wait for a reply.
+ pingAndWaitForReply(msg, TX_BATCH_SIZE_DEFAULT, TIMEOUT_DEFAULT, null);
+ }
+ catch (JMSException e)
+ {
+ _publish = false;
+ // log.debug("There was a JMSException: " + e.getMessage(), e);
+ }
+ catch (InterruptedException e)
+ {
+ _publish = false;
+ // log.debug("There was an interruption: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Sets a chained message listener. The message listener on this pinger, chains all its messages to the one set
+ * here.
+ *
+ * @param messageListener The chained message listener.
+ */
+ public void setChainedMessageListener(ChainedMessageListener messageListener)
+ {
+ _chainedMessageListener = messageListener;
+ }
+
+ /** Removes any chained message listeners from this pinger. */
+ public void removeChainedMessageListener()
+ {
+ _chainedMessageListener = null;
+ }
+
+ /**
+ * Generates a test message of the specified size, with the specified reply-to destination and persistence flag.
+ *
+ * @param replyQueue The reply-to destination for the message.
+ * @param messageSize The desired size of the message in bytes.
+ * @param persistent <tt>true</tt> if the message should use persistent delivery, <tt>false</tt> otherwise.
+ *
+ * @return A freshly generated test message.
+ *
+ * @throws javax.jms.JMSException All underlying JMSException are allowed to fall through.
+ */
+ public Message getTestMessage(Destination replyQueue, int messageSize, boolean persistent) throws JMSException
+ {
+ // return TestMessageFactory.newObjectMessage(_producerSession, replyQueue, messageSize, persistent);
+ return TestUtils.createTestMessageOfSize(_producerSession, messageSize);
+ }
+
+ /**
+ * Sets the current time in nanoseconds as the timestamp on the message.
+ *
+ * @param msg The message to timestamp.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ protected void setTimestamp(Message msg) throws JMSException
+ {
+ /*if (((AMQSession)_producerSession).isStrictAMQP())
+ {
+ ((AMQMessage)msg).setTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME), System.nanoTime());
+ }
+ else
+ {*/
+ msg.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
+ // }
+ }
+
+ /**
+ * Extracts the nanosecond timestamp from a message.
+ *
+ * @param msg The message to extract the time stamp from.
+ *
+ * @return The timestamp in nanos.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ protected long getTimestamp(Message msg) throws JMSException
+ {
+ /*if (((AMQSession)_producerSession).isStrictAMQP())
+ {
+ Long value = ((AMQMessage)msg).getTimestampProperty(new AMQShortString(MESSAGE_TIMESTAMP_PROPNAME));
+
+ return (value == null) ? 0L : value;
+ }
+ else
+ {*/
+ return msg.getLongProperty(PingPongProducer.MESSAGE_TIMESTAMP_PROPNAME);
+ // }
+ }
+
+ /**
+ * Stops the ping loop by clearing the publish flag. The current loop will complete when it notices that this flag
+ * has been cleared.
+ */
+ public void stop()
+ {
+ _publish = false;
+ }
+
+ /**
+ * Starts the producer and consumer connections.
+ *
+ * @throws JMSException Any JMSExceptions are allowed to fall through.
+ */
+ public void start() throws JMSException
+ {
+ // log.debug("public void start(): called");
+
+ _connection.start();
+ // log.debug("Producer started.");
+
+ for (int i = 0; i < _noOfConsumers; i++)
+ {
+ _consumerConnection[i].start();
+ // log.debug("Consumer " + i + " started.");
+ }
+ }
+
+ /** Implements a ping loop that repeatedly pings until the publish flag becomes false. */
+ public void run()
+ {
+ // Keep running until the publish flag is cleared.
+ while (_publish)
+ {
+ pingLoop();
+ }
+ }
+
+ /**
+ * Callback method, implementing ExceptionListener. This should be registered to listen for exceptions on the
+ * connection, this clears the publish flag which in turn will halt the ping loop.
+ *
+ * @param e The exception that triggered this callback method.
+ */
+ public void onException(JMSException e)
+ {
+ // log.debug("public void onException(JMSException e = " + e + "): called", e);
+ _publish = false;
+ }
+
+ /**
+ * Gets a shutdown hook that will cleanly shut this down when it is running the ping loop. This can be registered
+ * with the runtime system as a shutdown hook.
+ *
+ * @return A shutdown hook for the ping loop.
+ */
+ public Thread getShutdownHook()
+ {
+ return new Thread(new Runnable()
+ {
+ public void run()
+ {
+ stop();
+ }
+ });
+ }
+
+ /**
+ * Closes all of the producer and consumer connections.
+ *
+ * @throws JMSException All JMSException are allowed to fall through.
+ */
+ public void close() throws JMSException
+ {
+ // log.debug("public void close(): called");
+
+ try
+ {
+ if (_connection != null)
+ {
+ // log.debug("Before close producer connection.");
+ _connection.close();
+ // log.debug("Closed producer connection.");
+ }
+
+ for (int i = 0; i < _noOfConsumers; i++)
+ {
+ if (_consumerConnection[i] != null)
+ {
+ // log.debug("Before close consumer connection " + i + ".");
+ _consumerConnection[i].close();
+ // log.debug("Closed consumer connection " + i + ".");
+ }
+ }
+ }
+ finally
+ {
+ _connection = null;
+ _producerSession = null;
+ _consumerSession = null;
+ _consumerConnection = null;
+ _producer = null;
+ _consumer = null;
+ _pingDestinations = null;
+ _replyDestination = null;
+ }
+ }
+
+ /**
+ * Convenience method to commit the transaction on the specified controlSession. If the controlSession to commit on is not a
+ * transactional controlSession, this method does nothing (unless the failover after send flag is set).
+ *
+ * <p/>If the {@link #_failAfterSend} flag is set, this will prompt the user to kill the broker before the commit is
+ * applied. This flag applies whether the pinger is transactional or not.
+ *
+ * <p/>If the {@link #_failBeforeCommit} flag is set, this will prompt the user to kill the broker before the commit
+ * is applied. If the {@link #_failAfterCommit} flag is set, this will prompt the user to kill the broker after the
+ * commit is applied. These flags will only apply if using a transactional pinger.
+ *
+ * @param session The controlSession to commit
+ *
+ * @return <tt>true</tt> if the controlSession was committed, <tt>false</tt> if it was not.
+ *
+ * @throws javax.jms.JMSException If the commit fails and then the rollback fails.
+ *
+ * @todo Consider moving the fail after send logic into the send method. It is confusing to have it in this commit
+ * method, because commits only apply to transactional pingers, but fail after send applied to transactional and
+ * non-transactional alike.
+ */
+ protected boolean commitTx(Session session) throws JMSException
+ {
+ // log.debug("protected void commitTx(Session session): called");
+
+ boolean committed = false;
+
+ _failAfterSend = waitForUserToPromptOnFailure(_failAfterSend);
+
+ if (session.getTransacted())
+ {
+ // log.debug("Session is transacted.");
+
+ try
+ {
+ _failBeforeCommit = waitForUserToPromptOnFailure(_failBeforeCommit);
+
+ long start = System.nanoTime();
+ session.commit();
+ committed = true;
+ // log.debug("Time taken to commit :" + ((System.nanoTime() - start) / 1000000f) + " ms");
+
+ _failAfterCommit = waitForUserToPromptOnFailure(_failAfterCommit);
+
+ // log.debug("Session Commited.");
+ }
+ catch (JMSException e)
+ {
+ // log.debug("JMSException on commit:" + e.getMessage(), e);
+
+ try
+ {
+ session.rollback();
+ // log.debug("Message rolled back.");
+ }
+ catch (JMSException jmse)
+ {
+ // log.debug("JMSE on rollback:" + jmse.getMessage(), jmse);
+
+ // Both commit and rollback failed. Throw the rollback exception.
+ throw jmse;
+ }
+ }
+ }
+
+ return committed;
+ }
+
+ /**
+ * Outputs a prompt to the console and waits for the user to press return.
+ *
+ * @param prompt The prompt to display on the console.
+ */
+ public void waitForUser(String prompt)
+ {
+ System.out.println(prompt);
+
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ // Ignored.
+ }
+
+ System.out.println("Continuing.");
+ }
+
+ /**
+ * Gets the number of consumers that are listening to each destination in the test.
+ *
+ * @return int The number of consumers subscribing to each topic.
+ */
+ public int getConsumersPerDestination()
+ {
+ return _noOfConsumers;
+ }
+
+ /**
+ * Calculates how many pings are expected to be received for the given number sent.
+ *
+ * @param numpings The number of pings that will be sent.
+ *
+ * @return The number that should be received, for the test to pass.
+ */
+ public int getExpectedNumPings(int numpings)
+ {
+ // log.debug("public int getExpectedNumPings(int numpings = " + numpings + "): called");
+
+ // log.debug("Each ping will be received by " + (_isPubSub ? getConsumersPerDestination() : 1) + " consumers.");
+
+ return numpings * (_isPubSub ? getConsumersPerDestination() : 1);
+ }
+
+ /**
+ * Defines a chained message listener interface that can be attached to this pinger. Whenever this pinger's {@link
+ * PingPongProducer#onMessageWithConsumerNo} method is called, the chained listener set through the {@link
+ * PingPongProducer#setChainedMessageListener} method is passed the message, and the remaining expected count of
+ * messages with that correlation id.
+ *
+ * <p/>Provided only one pinger is producing messages with that correlation id, the chained listener will always be
+ * given unique message counts. It will always be called while the producer waiting for all messages to arrive is
+ * still blocked.
+ */
+ public static interface ChainedMessageListener
+ {
+ /**
+ * Notifies interested listeners about message arrival and important test stats, the number of messages
+ * remaining in the test, and the messages send timestamp.
+ *
+ * @param message The newly arrived message.
+ * @param remainingCount The number of messages left to complete the test.
+ * @param latency The nanosecond latency of the message.
+ *
+ * @throws JMSException Any JMS exceptions is allowed to fall through.
+ */
+ public void onMessage(Message message, int remainingCount, long latency) throws JMSException;
+ }
+
+ /**
+ * Holds information on each correlation id. The countdown latch, the current timeout timer... More stuff to be
+ * added to this: read/write lock to make onMessage more concurrent as described in class header comment.
+ */
+ protected static class PerCorrelationId
+ {
+ /** Holds a countdown on number of expected messages. */
+ CountDownLatch trafficLight;
+
+ /** Holds the last timestamp that the timeout was reset to. */
+ Long timeOutStart;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java
index 2610b32220..009254c612 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongTestPerf.java
@@ -1,251 +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.requestreply;
-
-import junit.framework.Assert;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.AsymptoticTestCase;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import javax.jms.*;
-
-/**
- * PingPongTestPerf is a full round trip ping test, that has been written with the intention of being scaled up to run
- * many times simultaneously to simluate many clients/producer/connections. A full round trip ping sends a message from
- * a producer to a conumer, then the consumer replies to the message on a temporary queue.
- *
- * <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of the number
- * of pings specified by the test size and time how long it takes for all of these to complete. This test may be scaled
- * up using a suitable JUnit test runner. See {@link org.apache.qpid.junit.extensions.TKTestRunner} for more
- * information on how to do this.
- *
- * <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
- * temporary queue for replies. This setup is only established once for all the test repeats, but each test threads
- * gets its own connection/producer/consumer, this is only re-established if the connection is lost.
- *
- * <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
- * is the name of the temporary queue, fires off many messages on the original queue and waits for them all to come
- * back on the temporary queue.
- *
- * <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * </table>
- */
-public class PingPongTestPerf extends AsymptoticTestCase
-{
- private static Logger _logger = Logger.getLogger(PingPongTestPerf.class);
-
- /** Thread local to hold the per-thread test setup fields. */
- ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
-
- // Set up a property reader to extract the test parameters from. Once ContextualProperties is available in
- // the project dependencies, use it to get property overrides for configurable tests and to notify the test runner
- // of the test parameters to log with the results. It also providers some basic type parsing convenience methods.
- // private Properties testParameters = System.getProperties();
- private ParsedProperties testParameters =
- TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/);
-
- public PingPongTestPerf(String name)
- {
- super(name);
-
- _logger.debug(testParameters);
-
- // Sets up the test parameters with defaults.
- /*testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME,
- Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.MESSAGE_SIZE_PROPNAME,
- Integer.toString(PingPongProducer.MESSAGE_SIZE_DEAFULT));
- testParameters.setPropertyIfNull(PingPongProducer.PING_QUEUE_NAME_PROPNAME,
- PingPongProducer.PING_QUEUE_NAME_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.PERSISTENT_MODE_PROPNAME,
- Boolean.toString(PingPongProducer.PERSISTENT_MODE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.TRANSACTED_PROPNAME,
- Boolean.toString(PingPongProducer.TRANSACTED_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.BROKER_PROPNAME, PingPongProducer.BROKER_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.USERNAME_PROPNAME, PingPongProducer.USERNAME_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.PASSWORD_PROPNAME, PingPongProducer.PASSWORD_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.VIRTUAL_HOST_PROPNAME, PingPongProducer.VIRTUAL_HOST_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.VERBOSE_PROPNAME,
- Boolean.toString(PingPongProducer.VERBOSE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.RATE_PROPNAME, Integer.toString(PingPongProducer.RATE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.PUBSUB_PROPNAME,
- Boolean.toString(PingPongProducer.PUBSUB_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME,
- Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.TIMEOUT_PROPNAME, Long.toString(PingPongProducer.TIMEOUT_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.DESTINATION_COUNT_PROPNAME,
- Integer.toString(PingPongProducer.DESTINATION_COUNT_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME,
- PingPongProducer.FAIL_AFTER_COMMIT_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME,
- PingPongProducer.FAIL_BEFORE_COMMIT_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_SEND_PROPNAME,
- PingPongProducer.FAIL_AFTER_SEND_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME,
- PingPongProducer.FAIL_BEFORE_SEND_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.FAIL_ONCE_PROPNAME, PingPongProducer.FAIL_ONCE_DEFAULT);
- testParameters.setPropertyIfNull(PingPongProducer.UNIQUE_DESTS_PROPNAME,
- Boolean.toString(PingPongProducer.UNIQUE_DESTS_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.ACK_MODE_PROPNAME,
- Integer.toString(PingPongProducer.ACK_MODE_DEFAULT));
- testParameters.setPropertyIfNull(PingPongProducer.PAUSE_AFTER_BATCH_PROPNAME,
- PingPongProducer.PAUSE_AFTER_BATCH_DEFAULT);*/
- }
-
- /**
- * Compile all the tests into a test suite.
- */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("Ping-Pong Performance Tests");
-
- // Run performance tests in read committed mode.
- suite.addTest(new PingPongTestPerf("testPingPongOk"));
-
- return suite;
- }
-
- private static void setSystemPropertyIfNull(String propName, String propValue)
- {
- if (System.getProperty(propName) == null)
- {
- System.setProperty(propName, propValue);
- }
- }
-
- public void testPingPongOk(int numPings) throws Exception
- {
- // Get the per thread test setup to run the test through.
- PerThreadSetup perThreadSetup = threadSetup.get();
-
- // Generate a sample message. This message is already time stamped and has its reply-to destination set.
- Message msg =
- perThreadSetup._testPingProducer.getTestMessage(perThreadSetup._testPingProducer.getReplyDestinations().get(0),
- testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
- testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
-
- // Send the message and wait for a reply.
- int numReplies =
- perThreadSetup._testPingProducer.pingAndWaitForReply(msg, numPings, PingPongProducer.TIMEOUT_DEFAULT, null);
-
- // Fail the test if the timeout was exceeded.
- if (numReplies != numPings)
- {
- Assert.fail("The ping timed out, got " + numReplies + " out of " + numPings);
- }
- }
-
- /**
- * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
- */
- public void threadSetUp()
- {
- try
- {
- PerThreadSetup perThreadSetup = new PerThreadSetup();
-
- // Extract the test set up paramaeters.
- String brokerDetails = testParameters.getProperty(PingPongProducer.BROKER_PROPNAME);
- String username = testParameters.getProperty(PingPongProducer.USERNAME_PROPNAME);
- String password = testParameters.getProperty(PingPongProducer.PASSWORD_PROPNAME);
- String virtualPath = testParameters.getProperty(PingPongProducer.VIRTUAL_HOST_PROPNAME);
- String destinationName = testParameters.getProperty(PingPongProducer.PING_QUEUE_NAME_PROPNAME);
- boolean persistent = testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME);
- boolean transacted = testParameters.getPropertyAsBoolean(PingPongProducer.TRANSACTED_PROPNAME);
- String selector = testParameters.getProperty(PingPongProducer.SELECTOR_PROPNAME);
- boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_PROPNAME);
- boolean pubsub = testParameters.getPropertyAsBoolean(PingPongProducer.PUBSUB_PROPNAME);
-
- synchronized (this)
- {
- // Establish a bounce back client on the ping queue to bounce back the pings.
- perThreadSetup._testPingBouncer =
- new PingPongBouncer(brokerDetails, username, password, virtualPath, destinationName, persistent,
- transacted, selector, verbose, pubsub);
-
- // Start the connections for client and producer running.
- perThreadSetup._testPingBouncer.getConnection().start();
-
- // Establish a ping-pong client on the ping queue to send the pings and receive replies with.
- perThreadSetup._testPingProducer = new PingPongProducer(testParameters);
- perThreadSetup._testPingProducer.establishConnection(true, true);
- perThreadSetup._testPingProducer.start();
- }
-
- // Attach the per-thread set to the thread.
- threadSetup.set(perThreadSetup);
- }
- catch (Exception e)
- {
- _logger.warn("There was an exception during per thread setup.", e);
- }
- }
-
- /**
- * Performs test fixture clean
- */
- public void threadTearDown()
- {
- _logger.debug("public void threadTearDown(): called");
-
- try
- {
- // Get the per thread test fixture.
- PerThreadSetup perThreadSetup = threadSetup.get();
-
- // Close the pingers so that it cleans up its connection cleanly.
- synchronized (this)
- {
- perThreadSetup._testPingProducer.close();
- // perThreadSetup._testPingBouncer.close();
- }
-
- // Ensure the per thread fixture is reclaimed.
- threadSetup.remove();
- }
- catch (JMSException e)
- {
- _logger.warn("There was an exception during per thread tear down.");
- }
- }
-
- protected static class PerThreadSetup
- {
- /**
- * Holds the test ping-pong producer.
- */
- private PingPongProducer _testPingProducer;
-
- /**
- * Holds the test ping client.
- */
- private PingPongBouncer _testPingBouncer;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.requestreply;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.AsymptoticTestCase;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import javax.jms.*;
+
+/**
+ * PingPongTestPerf is a full round trip ping test, that has been written with the intention of being scaled up to run
+ * many times simultaneously to simluate many clients/producer/connections. A full round trip ping sends a message from
+ * a producer to a conumer, then the consumer replies to the message on a temporary queue.
+ *
+ * <p/>A single run of the test using the default JUnit test runner will result in the sending and timing of the number
+ * of pings specified by the test size and time how long it takes for all of these to complete. This test may be scaled
+ * up using a suitable JUnit test runner. See {@link org.apache.qpid.junit.extensions.TKTestRunner} for more
+ * information on how to do this.
+ *
+ * <p/>The setup/teardown cycle establishes a connection to a broker and sets up a queue to send ping messages to and a
+ * temporary queue for replies. This setup is only established once for all the test repeats, but each test threads
+ * gets its own connection/producer/consumer, this is only re-established if the connection is lost.
+ *
+ * <p/>The test cycle is: Connects to a queue, creates a temporary queue, creates messages containing a property that
+ * is the name of the temporary queue, fires off many messages on the original queue and waits for them all to come
+ * back on the temporary queue.
+ *
+ * <p/>Configurable test properties: message size, transacted or not, persistent or not. Broker connection details.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * </table>
+ */
+public class PingPongTestPerf extends AsymptoticTestCase
+{
+ private static Logger _logger = Logger.getLogger(PingPongTestPerf.class);
+
+ /** Thread local to hold the per-thread test setup fields. */
+ ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
+
+ // Set up a property reader to extract the test parameters from. Once ContextualProperties is available in
+ // the project dependencies, use it to get property overrides for configurable tests and to notify the test runner
+ // of the test parameters to log with the results. It also providers some basic type parsing convenience methods.
+ // private Properties testParameters = System.getProperties();
+ private ParsedProperties testParameters =
+ TestContextProperties.getInstance(PingPongProducer.defaults /*System.getProperties()*/);
+
+ public PingPongTestPerf(String name)
+ {
+ super(name);
+
+ _logger.debug(testParameters);
+
+ // Sets up the test parameters with defaults.
+ /*testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.MESSAGE_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.MESSAGE_SIZE_DEAFULT));
+ testParameters.setPropertyIfNull(PingPongProducer.PING_QUEUE_NAME_PROPNAME,
+ PingPongProducer.PING_QUEUE_NAME_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.PERSISTENT_MODE_PROPNAME,
+ Boolean.toString(PingPongProducer.PERSISTENT_MODE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.TRANSACTED_PROPNAME,
+ Boolean.toString(PingPongProducer.TRANSACTED_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.BROKER_PROPNAME, PingPongProducer.BROKER_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.USERNAME_PROPNAME, PingPongProducer.USERNAME_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.PASSWORD_PROPNAME, PingPongProducer.PASSWORD_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.VIRTUAL_HOST_PROPNAME, PingPongProducer.VIRTUAL_HOST_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.VERBOSE_PROPNAME,
+ Boolean.toString(PingPongProducer.VERBOSE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.RATE_PROPNAME, Integer.toString(PingPongProducer.RATE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.PUBSUB_PROPNAME,
+ Boolean.toString(PingPongProducer.PUBSUB_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.TX_BATCH_SIZE_PROPNAME,
+ Integer.toString(PingPongProducer.TX_BATCH_SIZE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.TIMEOUT_PROPNAME, Long.toString(PingPongProducer.TIMEOUT_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.DESTINATION_COUNT_PROPNAME,
+ Integer.toString(PingPongProducer.DESTINATION_COUNT_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_COMMIT_PROPNAME,
+ PingPongProducer.FAIL_AFTER_COMMIT_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_COMMIT_PROPNAME,
+ PingPongProducer.FAIL_BEFORE_COMMIT_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.FAIL_AFTER_SEND_PROPNAME,
+ PingPongProducer.FAIL_AFTER_SEND_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.FAIL_BEFORE_SEND_PROPNAME,
+ PingPongProducer.FAIL_BEFORE_SEND_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.FAIL_ONCE_PROPNAME, PingPongProducer.FAIL_ONCE_DEFAULT);
+ testParameters.setPropertyIfNull(PingPongProducer.UNIQUE_DESTS_PROPNAME,
+ Boolean.toString(PingPongProducer.UNIQUE_DESTS_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.ACK_MODE_PROPNAME,
+ Integer.toString(PingPongProducer.ACK_MODE_DEFAULT));
+ testParameters.setPropertyIfNull(PingPongProducer.PAUSE_AFTER_BATCH_PROPNAME,
+ PingPongProducer.PAUSE_AFTER_BATCH_DEFAULT);*/
+ }
+
+ /**
+ * Compile all the tests into a test suite.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Ping-Pong Performance Tests");
+
+ // Run performance tests in read committed mode.
+ suite.addTest(new PingPongTestPerf("testPingPongOk"));
+
+ return suite;
+ }
+
+ private static void setSystemPropertyIfNull(String propName, String propValue)
+ {
+ if (System.getProperty(propName) == null)
+ {
+ System.setProperty(propName, propValue);
+ }
+ }
+
+ public void testPingPongOk(int numPings) throws Exception
+ {
+ // Get the per thread test setup to run the test through.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Generate a sample message. This message is already time stamped and has its reply-to destination set.
+ Message msg =
+ perThreadSetup._testPingProducer.getTestMessage(perThreadSetup._testPingProducer.getReplyDestinations().get(0),
+ testParameters.getPropertyAsInteger(PingPongProducer.MESSAGE_SIZE_PROPNAME),
+ testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME));
+
+ // Send the message and wait for a reply.
+ int numReplies =
+ perThreadSetup._testPingProducer.pingAndWaitForReply(msg, numPings, PingPongProducer.TIMEOUT_DEFAULT, null);
+
+ // Fail the test if the timeout was exceeded.
+ if (numReplies != numPings)
+ {
+ Assert.fail("The ping timed out, got " + numReplies + " out of " + numPings);
+ }
+ }
+
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ try
+ {
+ PerThreadSetup perThreadSetup = new PerThreadSetup();
+
+ // Extract the test set up paramaeters.
+ String brokerDetails = testParameters.getProperty(PingPongProducer.BROKER_PROPNAME);
+ String username = testParameters.getProperty(PingPongProducer.USERNAME_PROPNAME);
+ String password = testParameters.getProperty(PingPongProducer.PASSWORD_PROPNAME);
+ String virtualPath = testParameters.getProperty(PingPongProducer.VIRTUAL_HOST_PROPNAME);
+ String destinationName = testParameters.getProperty(PingPongProducer.PING_QUEUE_NAME_PROPNAME);
+ boolean persistent = testParameters.getPropertyAsBoolean(PingPongProducer.PERSISTENT_MODE_PROPNAME);
+ boolean transacted = testParameters.getPropertyAsBoolean(PingPongProducer.TRANSACTED_PROPNAME);
+ String selector = testParameters.getProperty(PingPongProducer.SELECTOR_PROPNAME);
+ boolean verbose = testParameters.getPropertyAsBoolean(PingPongProducer.VERBOSE_PROPNAME);
+ boolean pubsub = testParameters.getPropertyAsBoolean(PingPongProducer.PUBSUB_PROPNAME);
+
+ synchronized (this)
+ {
+ // Establish a bounce back client on the ping queue to bounce back the pings.
+ perThreadSetup._testPingBouncer =
+ new PingPongBouncer(brokerDetails, username, password, virtualPath, destinationName, persistent,
+ transacted, selector, verbose, pubsub);
+
+ // Start the connections for client and producer running.
+ perThreadSetup._testPingBouncer.getConnection().start();
+
+ // Establish a ping-pong client on the ping queue to send the pings and receive replies with.
+ perThreadSetup._testPingProducer = new PingPongProducer(testParameters);
+ perThreadSetup._testPingProducer.establishConnection(true, true);
+ perThreadSetup._testPingProducer.start();
+ }
+
+ // Attach the per-thread set to the thread.
+ threadSetup.set(perThreadSetup);
+ }
+ catch (Exception e)
+ {
+ _logger.warn("There was an exception during per thread setup.", e);
+ }
+ }
+
+ /**
+ * Performs test fixture clean
+ */
+ public void threadTearDown()
+ {
+ _logger.debug("public void threadTearDown(): called");
+
+ try
+ {
+ // Get the per thread test fixture.
+ PerThreadSetup perThreadSetup = threadSetup.get();
+
+ // Close the pingers so that it cleans up its connection cleanly.
+ synchronized (this)
+ {
+ perThreadSetup._testPingProducer.close();
+ // perThreadSetup._testPingBouncer.close();
+ }
+
+ // Ensure the per thread fixture is reclaimed.
+ threadSetup.remove();
+ }
+ catch (JMSException e)
+ {
+ _logger.warn("There was an exception during per thread tear down.");
+ }
+ }
+
+ protected static class PerThreadSetup
+ {
+ /**
+ * Holds the test ping-pong producer.
+ */
+ private PingPongProducer _testPingProducer;
+
+ /**
+ * Holds the test ping client.
+ */
+ private PingPongBouncer _testPingBouncer;
+ }
+}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java b/qpid/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
index f699295b06..0fcb0a8538 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/test/testcases/MessageThroughputPerf.java
@@ -1,199 +1,199 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.testcases;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-
-import org.apache.qpid.test.framework.Assertion;
-import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import org.apache.qpid.test.framework.MessagingTestConfigProperties;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import org.apache.qpid.junit.extensions.TestThreadAware;
-import org.apache.qpid.junit.extensions.TimingController;
-import org.apache.qpid.junit.extensions.TimingControllerAware;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import java.util.LinkedList;
-
-/**
- * MessageThroughputPerf runs a test over a {@link Circuit} controlled by the test parameters. It logs timings of
- * the time required to receive samples consisting of batches of messages.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Measure message throughput accross a test circuit. <td> {@link Circuit}
- * </table>
- *
- * @todo Check that all of the messages were sent. Check that the receiving end got the same number of messages as
- * the publishing end.
- *
- * @todo Set this up to run with zero sized tests. Size zero means send forever. Continuous sending to be interrupted
- * by completion of the test duration, or shutdown hook when the user presses Ctrl-C.
- */
-public class MessageThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(MessageThroughputPerf.class);
-
- /** Holds the timing controller, used to log test timings from self-timed tests. */
- private TimingController timingController;
-
- /** Thread local to hold the per-thread test setup fields. */
- ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
-
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public MessageThroughputPerf(String name)
- {
- super(name);
- }
-
- /**
- * Performs the a basic P2P test case.
- *
- * @param numMessages The number of messages to send in the test.
- */
- public void testThroughput(int numMessages)
- {
- log.debug("public void testThroughput(): called");
-
- PerThreadSetup setup = threadSetup.get();
- assertNoFailures(setup.testCircuit.test(numMessages, new LinkedList<Assertion>()));
- }
-
- /**
- * Should provide a translation from the junit method name of a test to its test case name as known to the test
- * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
- * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
- * name "TC2_BasicP2P".
- *
- * @param methodName The name of the JUnit test method.
- *
- * @return The name of the corresponding interop test case.
- */
- public String getTestCaseNameForTestMethod(String methodName)
- {
- log.debug("public String getTestCaseNameForTestMethod(String methodName = " + methodName + "): called");
-
- return "DEFAULT_CIRCUIT_TEST";
- }
-
- /**
- * Used by test runners that can supply a {@link org.apache.qpid.junit.extensions.TimingController} to set the
- * controller on an aware test.
- *
- * @param controller The timing controller.
- */
- public void setTimingController(TimingController controller)
- {
- timingController = controller;
- }
-
- /**
- * Overrides the parent setUp method so that the in-vm broker creation is not done on a per test basis.
- *
- * @throws Exception Any exceptions allowed to fall through and fail the test.
- */
- protected void setUp() throws Exception
- {
- NDC.push(getName());
-
- testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
- }
-
- /**
- * Overrides the parent setUp method so that the in-vm broker clean-up is not done on a per test basis.
- */
- protected void tearDown()
- {
- NDC.pop();
- }
-
- /**
- * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
- */
- public void threadSetUp()
- {
- // Run the test setup tasks. This may create an in-vm broker, if a decorator has injected a task for this.
- taskHandler.runSetupTasks();
-
- // Get the test parameters, any overrides on the command line will have been applied.
- ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
-
- // Customize the test parameters.
- testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST");
- testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue");
-
- // Get the test circuit factory to create test circuits and run the standard test procedure through.
- CircuitFactory circuitFactory = getCircuitFactory();
-
- // Create the test circuit. This projects the circuit onto the available test nodes and connects it up.
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Store the test configuration for the thread.
- PerThreadSetup setup = new PerThreadSetup();
- setup.testCircuit = testCircuit;
- threadSetup.set(setup);
- }
-
- /**
- * Called when a test thread is destroyed.
- */
- public void threadTearDown()
- {
- // Run the test teardown tasks. This may destroy the in-vm broker, if a decorator has injected a task for this.
- taskHandler.runSetupTasks();
- }
-
- /**
- * Holds the per-thread test configurations.
- */
- protected static class PerThreadSetup
- {
- /** Holds the test circuit to run tests on. */
- Circuit testCircuit;
- }
-
- /**
- * Compiles all the tests in this class into a suite.
- *
- * @return The test suite.
- */
- public static Test suite()
- {
- // Build a new test suite
- TestSuite suite = new TestSuite("Qpid Throughput Performance Tests");
-
- suite.addTest(new MessageThroughputPerf("testThroughput"));
-
- return suite;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.test.framework.Assertion;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import org.apache.qpid.junit.extensions.TestThreadAware;
+import org.apache.qpid.junit.extensions.TimingController;
+import org.apache.qpid.junit.extensions.TimingControllerAware;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import java.util.LinkedList;
+
+/**
+ * MessageThroughputPerf runs a test over a {@link Circuit} controlled by the test parameters. It logs timings of
+ * the time required to receive samples consisting of batches of messages.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Measure message throughput accross a test circuit. <td> {@link Circuit}
+ * </table>
+ *
+ * @todo Check that all of the messages were sent. Check that the receiving end got the same number of messages as
+ * the publishing end.
+ *
+ * @todo Set this up to run with zero sized tests. Size zero means send forever. Continuous sending to be interrupted
+ * by completion of the test duration, or shutdown hook when the user presses Ctrl-C.
+ */
+public class MessageThroughputPerf extends FrameworkBaseCase implements TimingControllerAware, TestThreadAware
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(MessageThroughputPerf.class);
+
+ /** Holds the timing controller, used to log test timings from self-timed tests. */
+ private TimingController timingController;
+
+ /** Thread local to hold the per-thread test setup fields. */
+ ThreadLocal<PerThreadSetup> threadSetup = new ThreadLocal<PerThreadSetup>();
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public MessageThroughputPerf(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Performs the a basic P2P test case.
+ *
+ * @param numMessages The number of messages to send in the test.
+ */
+ public void testThroughput(int numMessages)
+ {
+ log.debug("public void testThroughput(): called");
+
+ PerThreadSetup setup = threadSetup.get();
+ assertNoFailures(setup.testCircuit.test(numMessages, new LinkedList<Assertion>()));
+ }
+
+ /**
+ * Should provide a translation from the junit method name of a test to its test case name as known to the test
+ * clients that will run the test. The purpose of this is to convert the JUnit method name into the correct test
+ * case name to place into the test invite. For example the method "testP2P" might map onto the interop test case
+ * name "TC2_BasicP2P".
+ *
+ * @param methodName The name of the JUnit test method.
+ *
+ * @return The name of the corresponding interop test case.
+ */
+ public String getTestCaseNameForTestMethod(String methodName)
+ {
+ log.debug("public String getTestCaseNameForTestMethod(String methodName = " + methodName + "): called");
+
+ return "DEFAULT_CIRCUIT_TEST";
+ }
+
+ /**
+ * Used by test runners that can supply a {@link org.apache.qpid.junit.extensions.TimingController} to set the
+ * controller on an aware test.
+ *
+ * @param controller The timing controller.
+ */
+ public void setTimingController(TimingController controller)
+ {
+ timingController = controller;
+ }
+
+ /**
+ * Overrides the parent setUp method so that the in-vm broker creation is not done on a per test basis.
+ *
+ * @throws Exception Any exceptions allowed to fall through and fail the test.
+ */
+ protected void setUp() throws Exception
+ {
+ NDC.push(getName());
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+ }
+
+ /**
+ * Overrides the parent setUp method so that the in-vm broker clean-up is not done on a per test basis.
+ */
+ protected void tearDown()
+ {
+ NDC.pop();
+ }
+
+ /**
+ * Performs test fixture creation on a per thread basis. This will only be called once for each test thread.
+ */
+ public void threadSetUp()
+ {
+ // Run the test setup tasks. This may create an in-vm broker, if a decorator has injected a task for this.
+ taskHandler.runSetupTasks();
+
+ // Get the test parameters, any overrides on the command line will have been applied.
+ ParsedProperties testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ // Customize the test parameters.
+ testProps.setProperty("TEST_NAME", "DEFAULT_CIRCUIT_TEST");
+ testProps.setProperty(MessagingTestConfigProperties.SEND_DESTINATION_NAME_ROOT_PROPNAME, "testqueue");
+
+ // Get the test circuit factory to create test circuits and run the standard test procedure through.
+ CircuitFactory circuitFactory = getCircuitFactory();
+
+ // Create the test circuit. This projects the circuit onto the available test nodes and connects it up.
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Store the test configuration for the thread.
+ PerThreadSetup setup = new PerThreadSetup();
+ setup.testCircuit = testCircuit;
+ threadSetup.set(setup);
+ }
+
+ /**
+ * Called when a test thread is destroyed.
+ */
+ public void threadTearDown()
+ {
+ // Run the test teardown tasks. This may destroy the in-vm broker, if a decorator has injected a task for this.
+ taskHandler.runSetupTasks();
+ }
+
+ /**
+ * Holds the per-thread test configurations.
+ */
+ protected static class PerThreadSetup
+ {
+ /** Holds the test circuit to run tests on. */
+ Circuit testCircuit;
+ }
+
+ /**
+ * Compiles all the tests in this class into a suite.
+ *
+ * @return The test suite.
+ */
+ public static Test suite()
+ {
+ // Build a new test suite
+ TestSuite suite = new TestSuite("Qpid Throughput Performance Tests");
+
+ suite.addTest(new MessageThroughputPerf("testThroughput"));
+
+ return suite;
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
index 3a3b7f92dd..2d89d319d7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/MessagingTestConfigProperties.java
@@ -1,308 +1,308 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.exchange;
-
-import org.apache.qpid.jms.Session;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-/**
- * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
- * and test parameters for running a messaging test over that topology. A Properties object holding some of these
- * properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
- *
- * <p/>A complete list of the parameters, default values and comments on their usage is provided here:
- *
- * <p/><table><caption>Parameters</caption>
- * <tr><th> Parameter <th> Default <th> Comments
- * <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
- * <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
- * <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
- * <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
- * <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
- * <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
- * <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
- * <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
- * <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
- * <tr><td> username <td> guest <td> The username to access the broker with.
- * <tr><td> password <td> guest <td> The password to access the broker with.
- * <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
- * <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
- * <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
- * <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
- * <tr><td> uniqueDests <td> true <td> Whether each receiver only listens to one ping destination or all.
- * <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
- * <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
- * 0 - SESSION_TRANSACTED
- * 1 - AUTO_ACKNOWLEDGE
- * 2 - CLIENT_ACKNOWLEDGE
- * 3 - DUPS_OK_ACKNOWLEDGE
- * 257 - NO_ACKNOWLEDGE
- * 258 - PRE_ACKNOWLEDGE
- * <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
- * Limits the volume of messages currently buffered on the client
- * or broker. Can help scale test clients by limiting amount of buffered
- * data to avoid out of memory errors.
- * </table>
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide the names and defaults of all test parameters.
- * </table>
- */
-public class MessagingTestConfigProperties
-{
- // ====================== Connection Properties ==================================
-
- /** Holds the name of the default connection configuration. */
- public static final String CONNECTION_NAME = "broker";
-
- /** Holds the name of the property to get the initial context factory name from. */
- public static final String INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
-
- /** Defines the class to use as the initial context factory by default. */
- public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
-
- /** Holds the name of the default connection factory configuration property. */
- public static final String CONNECTION_PROPNAME = "connectionfactory.broker";
-
- /** Defeins the default connection configuration. */
- public static final String CONNECTION_DEFAULT = "amqp://guest:guest@clientid/?brokerlist='vm://:1'";
-
- /** Holds the name of the property to get the test broker url from. */
- public static final String BROKER_PROPNAME = "qpid.test.broker";
-
- /** Holds the default broker url for the test. */
- public static final String BROKER_DEFAULT = "vm://:1";
-
- /** Holds the name of the property to get the test broker virtual path. */
- public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
-
- /** Holds the default virtual path for the test. */
- public static final String VIRTUAL_HOST_DEFAULT = "";
-
- /** Holds the name of the property to get the broker access username from. */
- public static final String USERNAME_PROPNAME = "username";
-
- /** Holds the default broker log on username. */
- public static final String USERNAME_DEFAULT = "guest";
-
- /** Holds the name of the property to get the broker access password from. */
- public static final String PASSWORD_PROPNAME = "password";
-
- /** Holds the default broker log on password. */
- public static final String PASSWORD_DEFAULT = "guest";
-
- // ====================== Messaging Topology Properties ==========================
-
- /** Holds the name of the property to get the bind publisher procuder flag from. */
- public static final String PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
-
- /** Holds the default value of the publisher producer flag. */
- public static final boolean PUBLISHER_PRODUCER_BIND_DEFAULT = true;
-
- /** Holds the name of the property to get the bind publisher procuder flag from. */
- public static final String PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
-
- /** Holds the default value of the publisher consumer flag. */
- public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false;
-
- /** Holds the name of the property to get the bind receiver procuder flag from. */
- public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
-
- /** Holds the default value of the receiver producer flag. */
- public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false;
-
- /** Holds the name of the property to get the bind receiver procuder flag from. */
- public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
-
- /** Holds the default value of the receiver consumer flag. */
- public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true;
-
- /** Holds the name of the property to get the destination name root from. */
- public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
-
- /** Holds the root of the name of the default destination to send to. */
- public static final String SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
-
- /** Holds the name of the property to get the destination name root from. */
- public static final String RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
-
- /** Holds the root of the name of the default destination to send to. */
- public static final String RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
-
- /** Holds the name of the proeprty to get the destination count from. */
- public static final String DESTINATION_COUNT_PROPNAME = "destinationCount";
-
- /** Defines the default number of destinations to ping. */
- public static final int DESTINATION_COUNT_DEFAULT = 1;
-
- /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */
- public static final String PUBSUB_PROPNAME = "pubsub";
-
- /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
- public static final boolean PUBSUB_DEFAULT = false;
-
- // ====================== JMS Options and Flags =================================
-
- /** Holds the name of the property to get the test delivery mode from. */
- public static final String PERSISTENT_MODE_PROPNAME = "persistent";
-
- /** Holds the message delivery mode to use for the test. */
- public static final boolean PERSISTENT_MODE_DEFAULT = false;
-
- /** Holds the name of the property to get the test transactional mode from. */
- public static final String TRANSACTED_PROPNAME = "transacted";
-
- /** Holds the transactional mode to use for the test. */
- public static final boolean TRANSACTED_DEFAULT = false;
-
- /** Holds the name of the property to set the no local flag from. */
- public static final String NO_LOCAL_PROPNAME = "noLocal";
-
- /** Defines the default value of the no local flag to use when consuming messages. */
- public static final boolean NO_LOCAL_DEFAULT = false;
-
- /** Holds the name of the property to get the message acknowledgement mode from. */
- public static final String ACK_MODE_PROPNAME = "ackMode";
-
- /** Defines the default message acknowledgement mode. */
- public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
-
- /** Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. */
- public static final String DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
-
- /** Defines the default value of the durable subscriptions flag. */
- public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false;
-
- // ====================== Qpid Options and Flags ================================
-
- /** Holds the name of the property to set the exclusive flag from. */
- public static final String EXCLUSIVE_PROPNAME = "exclusive";
-
- /** Defines the default value of the exclusive flag to use when consuming messages. */
- public static final boolean EXCLUSIVE_DEFAULT = false;
-
- /** Holds the name of the property to set the immediate flag from. */
- public static final String IMMEDIATE_PROPNAME = "immediate";
-
- /** Defines the default value of the immediate flag to use when sending messages. */
- public static final boolean IMMEDIATE_DEFAULT = false;
-
- /** Holds the name of the property to set the mandatory flag from. */
- public static final String MANDATORY_PROPNAME = "mandatory";
-
- /** Defines the default value of the mandatory flag to use when sending messages. */
- public static final boolean MANDATORY_DEFAULT = false;
-
- /** Holds the name of the property to get the durable destinations flag from. */
- public static final String DURABLE_DESTS_PROPNAME = "durableDests";
-
- /** Default value for the durable destinations flag. */
- public static final boolean DURABLE_DESTS_DEFAULT = false;
-
- /** Holds the name of the proeprty to set the prefetch size from. */
- public static final String PREFECTH_PROPNAME = "prefetch";
-
- /** Defines the default prefetch size to use when consuming messages. */
- public static final int PREFETCH_DEFAULT = 100;
-
- // ====================== Common Test Parameters ================================
-
- /** Holds the name of the property to get the test message size from. */
- public static final String MESSAGE_SIZE_PROPNAME = "messageSize";
-
- /** Used to set up a default message size. */
- public static final int MESSAGE_SIZE_DEAFULT = 0;
-
- /** Holds the name of the property to get the message rate from. */
- public static final String RATE_PROPNAME = "rate";
-
- /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
- public static final int RATE_DEFAULT = 0;
-
- /** Holds the name of the proeprty to get the. */
- public static final String SELECTOR_PROPNAME = "selector";
-
- /** Holds the default message selector. */
- public static final String SELECTOR_DEFAULT = "";
-
- /** Holds the name of the property to get the waiting timeout for response messages. */
- public static final String TIMEOUT_PROPNAME = "timeout";
-
- /** Default time to wait before assuming that a ping has timed out. */
- public static final long TIMEOUT_DEFAULT = 30000;
-
- /** Holds the name of the property to get the commit batch size from. */
- public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
-
- /** Defines the default number of pings to send in each transaction when running transactionally. */
- public static final int TX_BATCH_SIZE_DEFAULT = 1;
-
- /** Holds the name of the property to set the maximum amount of pending message data for a producer to hold. */
- public static final String MAX_PENDING_PROPNAME = "maxPending";
-
- /** Defines the default maximum quantity of pending message data to allow producers to hold. */
- public static final int MAX_PENDING_DEFAULT = 0;
-
- /** Holds the name of the property to get the verbose mode proeprty from. */
- public static final String VERBOSE_PROPNAME = "verbose";
-
- /** Holds the default verbose mode. */
- public static final boolean VERBOSE_DEFAULT = false;
-
- /** Holds the default configuration properties. */
- public static ParsedProperties defaults = new ParsedProperties();
-
- static
- {
- defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
- defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
- defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
- defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
- defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
- defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
- defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT);
- defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
- defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
- defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
- defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
- defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
- defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
- defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
- defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
- defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
- defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
- defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
- defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
- defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
- defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
- defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
- defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
- defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
- defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
- defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
- defaults.setPropertyIfNull(PREFECTH_PROPNAME, PREFETCH_DEFAULT);
- defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
- defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
- defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
- defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.exchange;
+
+import org.apache.qpid.jms.Session;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+/**
+ * MessagingTestConfigProperties defines a set of property names and default values for specifying a messaging topology,
+ * and test parameters for running a messaging test over that topology. A Properties object holding some of these
+ * properties, superimposed onto the defaults, is used to establish test topologies and control test behaviour.
+ *
+ * <p/>A complete list of the parameters, default values and comments on their usage is provided here:
+ *
+ * <p/><table><caption>Parameters</caption>
+ * <tr><th> Parameter <th> Default <th> Comments
+ * <tr><td> messageSize <td> 0 <td> Message size in bytes. Not including any headers.
+ * <tr><td> destinationName <td> ping <td> The root name to use to generate destination names to ping.
+ * <tr><td> persistent <td> false <td> Determines whether peristent delivery is used.
+ * <tr><td> transacted <td> false <td> Determines whether messages are sent/received in transactions.
+ * <tr><td> broker <td> tcp://localhost:5672 <td> Determines the broker to connect to.
+ * <tr><td> virtualHost <td> test <td> Determines the virtual host to send all ping over.
+ * <tr><td> rate <td> 0 <td> The maximum rate (in hertz) to send messages at. 0 means no limit.
+ * <tr><td> verbose <td> false <td> The verbose flag for debugging. Prints to console on every message.
+ * <tr><td> pubsub <td> false <td> Whether to ping topics or queues. Uses p2p by default.
+ * <tr><td> username <td> guest <td> The username to access the broker with.
+ * <tr><td> password <td> guest <td> The password to access the broker with.
+ * <tr><td> selector <td> null <td> Not used. Defines a message selector to filter pings with.
+ * <tr><td> destinationCount <td> 1 <td> The number of receivers listening to the pings.
+ * <tr><td> timeout <td> 30000 <td> In milliseconds. The timeout to stop waiting for replies.
+ * <tr><td> commitBatchSize <td> 1 <td> The number of messages per transaction in transactional mode.
+ * <tr><td> uniqueDests <td> true <td> Whether each receiver only listens to one ping destination or all.
+ * <tr><td> durableDests <td> false <td> Whether or not durable destinations are used.
+ * <tr><td> ackMode <td> AUTO_ACK <td> The message acknowledgement mode. Possible values are:
+ * 0 - SESSION_TRANSACTED
+ * 1 - AUTO_ACKNOWLEDGE
+ * 2 - CLIENT_ACKNOWLEDGE
+ * 3 - DUPS_OK_ACKNOWLEDGE
+ * 257 - NO_ACKNOWLEDGE
+ * 258 - PRE_ACKNOWLEDGE
+ * <tr><td> maxPending <td> 0 <td> The maximum size in bytes, of messages sent but not yet received.
+ * Limits the volume of messages currently buffered on the client
+ * or broker. Can help scale test clients by limiting amount of buffered
+ * data to avoid out of memory errors.
+ * </table>
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide the names and defaults of all test parameters.
+ * </table>
+ */
+public class MessagingTestConfigProperties
+{
+ // ====================== Connection Properties ==================================
+
+ /** Holds the name of the default connection configuration. */
+ public static final String CONNECTION_NAME = "broker";
+
+ /** Holds the name of the property to get the initial context factory name from. */
+ public static final String INITIAL_CONTEXT_FACTORY_PROPNAME = "java.naming.factory.initial";
+
+ /** Defines the class to use as the initial context factory by default. */
+ public static final String INITIAL_CONTEXT_FACTORY_DEFAULT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory";
+
+ /** Holds the name of the default connection factory configuration property. */
+ public static final String CONNECTION_PROPNAME = "connectionfactory.broker";
+
+ /** Defeins the default connection configuration. */
+ public static final String CONNECTION_DEFAULT = "amqp://guest:guest@clientid/?brokerlist='vm://:1'";
+
+ /** Holds the name of the property to get the test broker url from. */
+ public static final String BROKER_PROPNAME = "qpid.test.broker";
+
+ /** Holds the default broker url for the test. */
+ public static final String BROKER_DEFAULT = "vm://:1";
+
+ /** Holds the name of the property to get the test broker virtual path. */
+ public static final String VIRTUAL_HOST_PROPNAME = "virtualHost";
+
+ /** Holds the default virtual path for the test. */
+ public static final String VIRTUAL_HOST_DEFAULT = "";
+
+ /** Holds the name of the property to get the broker access username from. */
+ public static final String USERNAME_PROPNAME = "username";
+
+ /** Holds the default broker log on username. */
+ public static final String USERNAME_DEFAULT = "guest";
+
+ /** Holds the name of the property to get the broker access password from. */
+ public static final String PASSWORD_PROPNAME = "password";
+
+ /** Holds the default broker log on password. */
+ public static final String PASSWORD_DEFAULT = "guest";
+
+ // ====================== Messaging Topology Properties ==========================
+
+ /** Holds the name of the property to get the bind publisher procuder flag from. */
+ public static final String PUBLISHER_PRODUCER_BIND_PROPNAME = "publisherProducerBind";
+
+ /** Holds the default value of the publisher producer flag. */
+ public static final boolean PUBLISHER_PRODUCER_BIND_DEFAULT = true;
+
+ /** Holds the name of the property to get the bind publisher procuder flag from. */
+ public static final String PUBLISHER_CONSUMER_BIND_PROPNAME = "publisherConsumerBind";
+
+ /** Holds the default value of the publisher consumer flag. */
+ public static final boolean PUBLISHER_CONSUMER_BIND_DEFAULT = false;
+
+ /** Holds the name of the property to get the bind receiver procuder flag from. */
+ public static final String RECEIVER_PRODUCER_BIND_PROPNAME = "receiverProducerBind";
+
+ /** Holds the default value of the receiver producer flag. */
+ public static final boolean RECEIVER_PRODUCER_BIND_DEFAULT = false;
+
+ /** Holds the name of the property to get the bind receiver procuder flag from. */
+ public static final String RECEIVER_CONSUMER_BIND_PROPNAME = "receiverConsumerBind";
+
+ /** Holds the default value of the receiver consumer flag. */
+ public static final boolean RECEIVER_CONSUMER_BIND_DEFAULT = true;
+
+ /** Holds the name of the property to get the destination name root from. */
+ public static final String SEND_DESTINATION_NAME_ROOT_PROPNAME = "sendDestinationRoot";
+
+ /** Holds the root of the name of the default destination to send to. */
+ public static final String SEND_DESTINATION_NAME_ROOT_DEFAULT = "sendTo";
+
+ /** Holds the name of the property to get the destination name root from. */
+ public static final String RECEIVE_DESTINATION_NAME_ROOT_PROPNAME = "receiveDestinationRoot";
+
+ /** Holds the root of the name of the default destination to send to. */
+ public static final String RECEIVE_DESTINATION_NAME_ROOT_DEFAULT = "receiveFrom";
+
+ /** Holds the name of the proeprty to get the destination count from. */
+ public static final String DESTINATION_COUNT_PROPNAME = "destinationCount";
+
+ /** Defines the default number of destinations to ping. */
+ public static final int DESTINATION_COUNT_DEFAULT = 1;
+
+ /** Holds the name of the property to get the p2p or pub/sub messaging mode from. */
+ public static final String PUBSUB_PROPNAME = "pubsub";
+
+ /** Holds the pub/sub mode default, true means ping a topic, false means ping a queue. */
+ public static final boolean PUBSUB_DEFAULT = false;
+
+ // ====================== JMS Options and Flags =================================
+
+ /** Holds the name of the property to get the test delivery mode from. */
+ public static final String PERSISTENT_MODE_PROPNAME = "persistent";
+
+ /** Holds the message delivery mode to use for the test. */
+ public static final boolean PERSISTENT_MODE_DEFAULT = false;
+
+ /** Holds the name of the property to get the test transactional mode from. */
+ public static final String TRANSACTED_PROPNAME = "transacted";
+
+ /** Holds the transactional mode to use for the test. */
+ public static final boolean TRANSACTED_DEFAULT = false;
+
+ /** Holds the name of the property to set the no local flag from. */
+ public static final String NO_LOCAL_PROPNAME = "noLocal";
+
+ /** Defines the default value of the no local flag to use when consuming messages. */
+ public static final boolean NO_LOCAL_DEFAULT = false;
+
+ /** Holds the name of the property to get the message acknowledgement mode from. */
+ public static final String ACK_MODE_PROPNAME = "ackMode";
+
+ /** Defines the default message acknowledgement mode. */
+ public static final int ACK_MODE_DEFAULT = Session.AUTO_ACKNOWLEDGE;
+
+ /** Holds the name of the property to get the durable subscriptions flag from, when doing pub/sub messaging. */
+ public static final String DURABLE_SUBSCRIPTION_PROPNAME = "durableSubscription";
+
+ /** Defines the default value of the durable subscriptions flag. */
+ public static final boolean DURABLE_SUBSCRIPTION_DEFAULT = false;
+
+ // ====================== Qpid Options and Flags ================================
+
+ /** Holds the name of the property to set the exclusive flag from. */
+ public static final String EXCLUSIVE_PROPNAME = "exclusive";
+
+ /** Defines the default value of the exclusive flag to use when consuming messages. */
+ public static final boolean EXCLUSIVE_DEFAULT = false;
+
+ /** Holds the name of the property to set the immediate flag from. */
+ public static final String IMMEDIATE_PROPNAME = "immediate";
+
+ /** Defines the default value of the immediate flag to use when sending messages. */
+ public static final boolean IMMEDIATE_DEFAULT = false;
+
+ /** Holds the name of the property to set the mandatory flag from. */
+ public static final String MANDATORY_PROPNAME = "mandatory";
+
+ /** Defines the default value of the mandatory flag to use when sending messages. */
+ public static final boolean MANDATORY_DEFAULT = false;
+
+ /** Holds the name of the property to get the durable destinations flag from. */
+ public static final String DURABLE_DESTS_PROPNAME = "durableDests";
+
+ /** Default value for the durable destinations flag. */
+ public static final boolean DURABLE_DESTS_DEFAULT = false;
+
+ /** Holds the name of the proeprty to set the prefetch size from. */
+ public static final String PREFECTH_PROPNAME = "prefetch";
+
+ /** Defines the default prefetch size to use when consuming messages. */
+ public static final int PREFETCH_DEFAULT = 100;
+
+ // ====================== Common Test Parameters ================================
+
+ /** Holds the name of the property to get the test message size from. */
+ public static final String MESSAGE_SIZE_PROPNAME = "messageSize";
+
+ /** Used to set up a default message size. */
+ public static final int MESSAGE_SIZE_DEAFULT = 0;
+
+ /** Holds the name of the property to get the message rate from. */
+ public static final String RATE_PROPNAME = "rate";
+
+ /** Defines the default rate (in pings per second) to send pings at. 0 means as fast as possible, no restriction. */
+ public static final int RATE_DEFAULT = 0;
+
+ /** Holds the name of the proeprty to get the. */
+ public static final String SELECTOR_PROPNAME = "selector";
+
+ /** Holds the default message selector. */
+ public static final String SELECTOR_DEFAULT = "";
+
+ /** Holds the name of the property to get the waiting timeout for response messages. */
+ public static final String TIMEOUT_PROPNAME = "timeout";
+
+ /** Default time to wait before assuming that a ping has timed out. */
+ public static final long TIMEOUT_DEFAULT = 30000;
+
+ /** Holds the name of the property to get the commit batch size from. */
+ public static final String TX_BATCH_SIZE_PROPNAME = "commitBatchSize";
+
+ /** Defines the default number of pings to send in each transaction when running transactionally. */
+ public static final int TX_BATCH_SIZE_DEFAULT = 1;
+
+ /** Holds the name of the property to set the maximum amount of pending message data for a producer to hold. */
+ public static final String MAX_PENDING_PROPNAME = "maxPending";
+
+ /** Defines the default maximum quantity of pending message data to allow producers to hold. */
+ public static final int MAX_PENDING_DEFAULT = 0;
+
+ /** Holds the name of the property to get the verbose mode proeprty from. */
+ public static final String VERBOSE_PROPNAME = "verbose";
+
+ /** Holds the default verbose mode. */
+ public static final boolean VERBOSE_DEFAULT = false;
+
+ /** Holds the default configuration properties. */
+ public static ParsedProperties defaults = new ParsedProperties();
+
+ static
+ {
+ defaults.setPropertyIfNull(INITIAL_CONTEXT_FACTORY_PROPNAME, INITIAL_CONTEXT_FACTORY_DEFAULT);
+ defaults.setPropertyIfNull(CONNECTION_PROPNAME, CONNECTION_DEFAULT);
+ defaults.setPropertyIfNull(MESSAGE_SIZE_PROPNAME, MESSAGE_SIZE_DEAFULT);
+ defaults.setPropertyIfNull(PUBLISHER_PRODUCER_BIND_PROPNAME, PUBLISHER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(PUBLISHER_CONSUMER_BIND_PROPNAME, PUBLISHER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_PRODUCER_BIND_PROPNAME, RECEIVER_PRODUCER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVER_CONSUMER_BIND_PROPNAME, RECEIVER_CONSUMER_BIND_DEFAULT);
+ defaults.setPropertyIfNull(SEND_DESTINATION_NAME_ROOT_PROPNAME, SEND_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(RECEIVE_DESTINATION_NAME_ROOT_PROPNAME, RECEIVE_DESTINATION_NAME_ROOT_DEFAULT);
+ defaults.setPropertyIfNull(PERSISTENT_MODE_PROPNAME, PERSISTENT_MODE_DEFAULT);
+ defaults.setPropertyIfNull(TRANSACTED_PROPNAME, TRANSACTED_DEFAULT);
+ defaults.setPropertyIfNull(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setPropertyIfNull(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ defaults.setPropertyIfNull(RATE_PROPNAME, RATE_DEFAULT);
+ defaults.setPropertyIfNull(VERBOSE_PROPNAME, VERBOSE_DEFAULT);
+ defaults.setPropertyIfNull(PUBSUB_PROPNAME, PUBSUB_DEFAULT);
+ defaults.setPropertyIfNull(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setPropertyIfNull(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+ defaults.setPropertyIfNull(SELECTOR_PROPNAME, SELECTOR_DEFAULT);
+ defaults.setPropertyIfNull(DESTINATION_COUNT_PROPNAME, DESTINATION_COUNT_DEFAULT);
+ defaults.setPropertyIfNull(TIMEOUT_PROPNAME, TIMEOUT_DEFAULT);
+ defaults.setPropertyIfNull(TX_BATCH_SIZE_PROPNAME, TX_BATCH_SIZE_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_DESTS_PROPNAME, DURABLE_DESTS_DEFAULT);
+ defaults.setPropertyIfNull(ACK_MODE_PROPNAME, ACK_MODE_DEFAULT);
+ defaults.setPropertyIfNull(DURABLE_SUBSCRIPTION_PROPNAME, DURABLE_SUBSCRIPTION_DEFAULT);
+ defaults.setPropertyIfNull(MAX_PENDING_PROPNAME, MAX_PENDING_DEFAULT);
+ defaults.setPropertyIfNull(PREFECTH_PROPNAME, PREFETCH_DEFAULT);
+ defaults.setPropertyIfNull(NO_LOCAL_PROPNAME, NO_LOCAL_DEFAULT);
+ defaults.setPropertyIfNull(EXCLUSIVE_PROPNAME, EXCLUSIVE_DEFAULT);
+ defaults.setPropertyIfNull(IMMEDIATE_PROPNAME, IMMEDIATE_DEFAULT);
+ defaults.setPropertyIfNull(MANDATORY_PROPNAME, MANDATORY_DEFAULT);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
index a6a2bbb80f..bae3f844d7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java
@@ -1,312 +1,312 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.server.exchange;
-
-import junit.framework.TestCase;
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.util.NullApplicationRegistry;
-import org.apache.qpid.client.*;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.url.AMQBindingURL;
-import org.apache.qpid.url.BindingURL;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.FieldTable;
-
-import javax.jms.*;
-import java.util.List;
-import java.util.Collections;
-import java.util.ArrayList;
-
-public class ReturnUnroutableMandatoryMessageTest extends TestCase implements ExceptionListener
-{
- private static final Logger _logger = Logger.getLogger(ReturnUnroutableMandatoryMessageTest.class);
-
- private final List<Message> _bouncedMessageList = Collections.synchronizedList(new ArrayList<Message>());
- private static final String VIRTUALHOST = "test";
- private static final String BROKER = "vm://:1";
-
- static
- {
- String workdir = System.getProperty("QPID_WORK");
- if (workdir == null || workdir.equals(""))
- {
- String tempdir = System.getProperty("java.io.tmpdir");
- System.out.println("QPID_WORK not set using tmp directory: " + tempdir);
- System.setProperty("QPID_WORK", tempdir);
- }
-// DOMConfigurator.configure("../broker/etc/log4j.xml");
- }
-
- protected void setUp() throws Exception
- {
- super.setUp();
- TransportConnection.createVMBroker(1);
- ApplicationRegistry.initialise(new NullApplicationRegistry(), 1);
- }
-
- protected void tearDown() throws Exception
- {
- super.tearDown();
- TransportConnection.killAllVMBrokers();
- }
-
- /**
- * Tests that mandatory message which are not routable are returned to the producer
- *
- * @throws Exception
- */
- public void testReturnUnroutableMandatoryMessage_HEADERS() throws Exception
- {
- _bouncedMessageList.clear();
- Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
-
- AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- AMQHeadersExchange queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS + "://" + ExchangeDefaults.HEADERS_EXCHANGE_NAME + "/test/queue1?" + BindingURL.OPTION_ROUTING_KEY + "='F0000=1'"));
- FieldTable ft = new FieldTable();
- ft.setString("F1000", "1");
- MessageConsumer consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String) null, ft);
-
- //force synch to ensure the consumer has resulted in a bound queue
- //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
- // This is the default now
-
- Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
-
- con2.setExceptionListener(this);
- AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- // Need to start the "producer" connection in order to receive bounced messages
- _logger.info("Starting producer connection");
- con2.start();
-
-
- MessageProducer nonMandatoryProducer = producerSession.createProducer(queue, false, false);
- MessageProducer mandatoryProducer = producerSession.createProducer(queue);
-
- // First test - should neither be bounced nor routed
- _logger.info("Sending non-routable non-mandatory message");
- TextMessage msg1 = producerSession.createTextMessage("msg1");
- nonMandatoryProducer.send(msg1);
-
- // Second test - should be bounced
- _logger.info("Sending non-routable mandatory message");
- TextMessage msg2 = producerSession.createTextMessage("msg2");
- mandatoryProducer.send(msg2);
-
- // Third test - should be routed
- _logger.info("Sending routable message");
- TextMessage msg3 = producerSession.createTextMessage("msg3");
- msg3.setStringProperty("F1000", "1");
- mandatoryProducer.send(msg3);
-
-
- _logger.info("Starting consumer connection");
- con.start();
- TextMessage tm = (TextMessage) consumer.receive(1000L);
-
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg3".equals(tm.getText()));
-
- try
- {
- Thread.sleep(1000L);
- }
- catch (InterruptedException e)
- {
- ;
- }
-
- assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
- Message m = _bouncedMessageList.get(0);
- assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
-
- con.close();
- con2.close();
-
-
- }
-
- public void testReturnUnroutableMandatoryMessage_QUEUE() throws Exception
- {
- _bouncedMessageList.clear();
- Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
-
- AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- AMQQueue valid_queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "testReturnUnroutableMandatoryMessage_QUEUE");
- AMQQueue invalid_queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "testReturnUnroutableMandatoryMessage_QUEUE_INVALID");
- MessageConsumer consumer = consumerSession.createConsumer(valid_queue);
-
- //force synch to ensure the consumer has resulted in a bound queue
- //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
- // This is the default now
-
- Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
-
- con2.setExceptionListener(this);
- AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- // Need to start the "producer" connection in order to receive bounced messages
- _logger.info("Starting producer connection");
- con2.start();
-
-
- MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_queue, false, false);
- MessageProducer mandatoryProducer = producerSession.createProducer(invalid_queue);
-
- // First test - should be routed
- _logger.info("Sending non-mandatory message");
- TextMessage msg1 = producerSession.createTextMessage("msg1");
- nonMandatoryProducer.send(msg1);
-
- // Second test - should be bounced
- _logger.info("Sending non-routable mandatory message");
- TextMessage msg2 = producerSession.createTextMessage("msg2");
- mandatoryProducer.send(msg2);
-
-
- _logger.info("Starting consumer connection");
- con.start();
- TextMessage tm = (TextMessage) consumer.receive(1000L);
-
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
-
- try
- {
- Thread.sleep(1000L);
- }
- catch (InterruptedException e)
- {
- ;
- }
-
- assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
- Message m = _bouncedMessageList.get(0);
- assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
-
- con.close();
- con2.close();
- }
-
-
- public void testReturnUnroutableMandatoryMessage_TOPIC() throws Exception
- {
- _bouncedMessageList.clear();
- Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
-
-
- AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- AMQTopic valid_topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, "test.Return.Unroutable.Mandatory.Message.TOPIC");
- AMQTopic invalid_topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, "test.Return.Unroutable.Mandatory.Message.TOPIC.invalid");
- MessageConsumer consumer = consumerSession.createConsumer(valid_topic);
-
- //force synch to ensure the consumer has resulted in a bound queue
- //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
- // This is the default now
-
- Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
-
- con2.setExceptionListener(this);
- AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
-
- // Need to start the "producer" connection in order to receive bounced messages
- _logger.info("Starting producer connection");
- con2.start();
-
-
- MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_topic, false, false);
- MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic);
-
- // First test - should be routed
- _logger.info("Sending non-mandatory message");
- TextMessage msg1 = producerSession.createTextMessage("msg1");
- nonMandatoryProducer.send(msg1);
-
- // Second test - should be bounced
- _logger.info("Sending non-routable mandatory message");
- TextMessage msg2 = producerSession.createTextMessage("msg2");
- mandatoryProducer.send(msg2);
-
-
- _logger.info("Starting consumer connection");
- con.start();
- TextMessage tm = (TextMessage) consumer.receive(1000L);
-
- assertTrue("No message routed to receiver", tm != null);
- assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
-
- try
- {
- Thread.sleep(1000L);
- }
- catch (InterruptedException e)
- {
- ;
- }
-
- assertEquals("Wrong number of messages bounced: ", 1, _bouncedMessageList.size());
- Message m = _bouncedMessageList.get(0);
- assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
-
-
- con.close();
- con2.close();
- }
-
-
- public static junit.framework.Test suite()
- {
- return new junit.framework.TestSuite(ReturnUnroutableMandatoryMessageTest.class);
- }
-
- public void onException(JMSException jmsException)
- {
-
- Exception linkedException = null;
- try
- {
- linkedException = jmsException.getLinkedException();
- } catch (Exception e)
- {
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
- }
- if (linkedException instanceof AMQNoRouteException)
- {
- AMQNoRouteException noRoute = (AMQNoRouteException) linkedException;
- Message bounced = (Message) noRoute.getUndeliveredMessage();
- _bouncedMessageList.add(bounced);
- _logger.info("Caught expected NoRouteException");
- }
- else
- {
- _logger.warn("Caught exception on producer: ", jmsException);
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.exchange;
+
+import junit.framework.TestCase;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.util.NullApplicationRegistry;
+import org.apache.qpid.client.*;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.url.AMQBindingURL;
+import org.apache.qpid.url.BindingURL;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.FieldTable;
+
+import javax.jms.*;
+import java.util.List;
+import java.util.Collections;
+import java.util.ArrayList;
+
+public class ReturnUnroutableMandatoryMessageTest extends TestCase implements ExceptionListener
+{
+ private static final Logger _logger = Logger.getLogger(ReturnUnroutableMandatoryMessageTest.class);
+
+ private final List<Message> _bouncedMessageList = Collections.synchronizedList(new ArrayList<Message>());
+ private static final String VIRTUALHOST = "test";
+ private static final String BROKER = "vm://:1";
+
+ static
+ {
+ String workdir = System.getProperty("QPID_WORK");
+ if (workdir == null || workdir.equals(""))
+ {
+ String tempdir = System.getProperty("java.io.tmpdir");
+ System.out.println("QPID_WORK not set using tmp directory: " + tempdir);
+ System.setProperty("QPID_WORK", tempdir);
+ }
+// DOMConfigurator.configure("../broker/etc/log4j.xml");
+ }
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+ ApplicationRegistry.initialise(new NullApplicationRegistry(), 1);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ TransportConnection.killAllVMBrokers();
+ }
+
+ /**
+ * Tests that mandatory message which are not routable are returned to the producer
+ *
+ * @throws Exception
+ */
+ public void testReturnUnroutableMandatoryMessage_HEADERS() throws Exception
+ {
+ _bouncedMessageList.clear();
+ Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
+
+
+ AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ AMQHeadersExchange queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS + "://" + ExchangeDefaults.HEADERS_EXCHANGE_NAME + "/test/queue1?" + BindingURL.OPTION_ROUTING_KEY + "='F0000=1'"));
+ FieldTable ft = new FieldTable();
+ ft.setString("F1000", "1");
+ MessageConsumer consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String) null, ft);
+
+ //force synch to ensure the consumer has resulted in a bound queue
+ //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
+ // This is the default now
+
+ Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
+
+ con2.setExceptionListener(this);
+ AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ // Need to start the "producer" connection in order to receive bounced messages
+ _logger.info("Starting producer connection");
+ con2.start();
+
+
+ MessageProducer nonMandatoryProducer = producerSession.createProducer(queue, false, false);
+ MessageProducer mandatoryProducer = producerSession.createProducer(queue);
+
+ // First test - should neither be bounced nor routed
+ _logger.info("Sending non-routable non-mandatory message");
+ TextMessage msg1 = producerSession.createTextMessage("msg1");
+ nonMandatoryProducer.send(msg1);
+
+ // Second test - should be bounced
+ _logger.info("Sending non-routable mandatory message");
+ TextMessage msg2 = producerSession.createTextMessage("msg2");
+ mandatoryProducer.send(msg2);
+
+ // Third test - should be routed
+ _logger.info("Sending routable message");
+ TextMessage msg3 = producerSession.createTextMessage("msg3");
+ msg3.setStringProperty("F1000", "1");
+ mandatoryProducer.send(msg3);
+
+
+ _logger.info("Starting consumer connection");
+ con.start();
+ TextMessage tm = (TextMessage) consumer.receive(1000L);
+
+ assertTrue("No message routed to receiver", tm != null);
+ assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg3".equals(tm.getText()));
+
+ try
+ {
+ Thread.sleep(1000L);
+ }
+ catch (InterruptedException e)
+ {
+ ;
+ }
+
+ assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
+ Message m = _bouncedMessageList.get(0);
+ assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
+
+
+ con.close();
+ con2.close();
+
+
+ }
+
+ public void testReturnUnroutableMandatoryMessage_QUEUE() throws Exception
+ {
+ _bouncedMessageList.clear();
+ Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
+
+
+ AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ AMQQueue valid_queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "testReturnUnroutableMandatoryMessage_QUEUE");
+ AMQQueue invalid_queue = new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "testReturnUnroutableMandatoryMessage_QUEUE_INVALID");
+ MessageConsumer consumer = consumerSession.createConsumer(valid_queue);
+
+ //force synch to ensure the consumer has resulted in a bound queue
+ //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
+ // This is the default now
+
+ Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
+
+ con2.setExceptionListener(this);
+ AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ // Need to start the "producer" connection in order to receive bounced messages
+ _logger.info("Starting producer connection");
+ con2.start();
+
+
+ MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_queue, false, false);
+ MessageProducer mandatoryProducer = producerSession.createProducer(invalid_queue);
+
+ // First test - should be routed
+ _logger.info("Sending non-mandatory message");
+ TextMessage msg1 = producerSession.createTextMessage("msg1");
+ nonMandatoryProducer.send(msg1);
+
+ // Second test - should be bounced
+ _logger.info("Sending non-routable mandatory message");
+ TextMessage msg2 = producerSession.createTextMessage("msg2");
+ mandatoryProducer.send(msg2);
+
+
+ _logger.info("Starting consumer connection");
+ con.start();
+ TextMessage tm = (TextMessage) consumer.receive(1000L);
+
+ assertTrue("No message routed to receiver", tm != null);
+ assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
+
+ try
+ {
+ Thread.sleep(1000L);
+ }
+ catch (InterruptedException e)
+ {
+ ;
+ }
+
+ assertTrue("Wrong number of messages bounced (expect 1): " + _bouncedMessageList.size(), _bouncedMessageList.size() == 1);
+ Message m = _bouncedMessageList.get(0);
+ assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
+
+
+ con.close();
+ con2.close();
+ }
+
+
+ public void testReturnUnroutableMandatoryMessage_TOPIC() throws Exception
+ {
+ _bouncedMessageList.clear();
+ Connection con = new AMQConnection(BROKER, "guest", "guest", "consumer1", VIRTUALHOST);
+
+
+ AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ AMQTopic valid_topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, "test.Return.Unroutable.Mandatory.Message.TOPIC");
+ AMQTopic invalid_topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, "test.Return.Unroutable.Mandatory.Message.TOPIC.invalid");
+ MessageConsumer consumer = consumerSession.createConsumer(valid_topic);
+
+ //force synch to ensure the consumer has resulted in a bound queue
+ //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
+ // This is the default now
+
+ Connection con2 = new AMQConnection(BROKER, "guest", "guest", "producer1", VIRTUALHOST);
+
+ con2.setExceptionListener(this);
+ AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+ // Need to start the "producer" connection in order to receive bounced messages
+ _logger.info("Starting producer connection");
+ con2.start();
+
+
+ MessageProducer nonMandatoryProducer = producerSession.createProducer(valid_topic, false, false);
+ MessageProducer mandatoryProducer = producerSession.createProducer(invalid_topic);
+
+ // First test - should be routed
+ _logger.info("Sending non-mandatory message");
+ TextMessage msg1 = producerSession.createTextMessage("msg1");
+ nonMandatoryProducer.send(msg1);
+
+ // Second test - should be bounced
+ _logger.info("Sending non-routable mandatory message");
+ TextMessage msg2 = producerSession.createTextMessage("msg2");
+ mandatoryProducer.send(msg2);
+
+
+ _logger.info("Starting consumer connection");
+ con.start();
+ TextMessage tm = (TextMessage) consumer.receive(1000L);
+
+ assertTrue("No message routed to receiver", tm != null);
+ assertTrue("Wrong message routed to receiver: " + tm.getText(), "msg1".equals(tm.getText()));
+
+ try
+ {
+ Thread.sleep(1000L);
+ }
+ catch (InterruptedException e)
+ {
+ ;
+ }
+
+ assertEquals("Wrong number of messages bounced: ", 1, _bouncedMessageList.size());
+ Message m = _bouncedMessageList.get(0);
+ assertTrue("Wrong message bounced: " + m.toString(), m.toString().contains("msg2"));
+
+
+ con.close();
+ con2.close();
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(ReturnUnroutableMandatoryMessageTest.class);
+ }
+
+ public void onException(JMSException jmsException)
+ {
+
+ Exception linkedException = null;
+ try
+ {
+ linkedException = jmsException.getLinkedException();
+ } catch (Exception e)
+ {
+ e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ }
+ if (linkedException instanceof AMQNoRouteException)
+ {
+ AMQNoRouteException noRoute = (AMQNoRouteException) linkedException;
+ Message bounced = (Message) noRoute.getUndeliveredMessage();
+ _bouncedMessageList.add(bounced);
+ _logger.info("Caught expected NoRouteException");
+ }
+ else
+ {
+ _logger.warn("Caught exception on producer: ", jmsException);
+ }
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java
index 706d99ffe2..13465741bd 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/AMQPPublisher.java
@@ -1,54 +1,54 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-/**
- * An AMQPPublisher represents the status of the publishing side of a test circuit that exposes AMQP specific features.
- * Its provides additional assertions not available through the plain JMS {@link Publisher} interface.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
- * <tr><td> Provide assertion that the publishers received a no route error code on every message.
- * </table>
- */
-public interface AMQPPublisher extends Publisher
-{
- /**
- * Provides an assertion that the publisher got a no consumers exception on every message.
- *
- * @param testProps The test configuration properties.
- *
- * @return An assertion that the publisher got a no consumers exception on every message.
- */
- Assertion noConsumersAssertion(ParsedProperties testProps);
-
- /**
- * Provides an assertion that the publisher got a no rout exception on every message.
- *
- * @param testProps The test configuration properties.
- *
- * @return An assertion that the publisher got a no rout exception on every message.
- */
- Assertion noRouteAssertion(ParsedProperties testProps);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+/**
+ * An AMQPPublisher represents the status of the publishing side of a test circuit that exposes AMQP specific features.
+ * Its provides additional assertions not available through the plain JMS {@link Publisher} interface.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Provide assertion that the publishers received a no consumers error code on every message.
+ * <tr><td> Provide assertion that the publishers received a no route error code on every message.
+ * </table>
+ */
+public interface AMQPPublisher extends Publisher
+{
+ /**
+ * Provides an assertion that the publisher got a no consumers exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no consumers exception on every message.
+ */
+ Assertion noConsumersAssertion(ParsedProperties testProps);
+
+ /**
+ * Provides an assertion that the publisher got a no rout exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no rout exception on every message.
+ */
+ Assertion noRouteAssertion(ParsedProperties testProps);
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java
index e8b7da2537..41614f92fc 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/BrokerLifecycleAware.java
@@ -1,70 +1,70 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-/**
- * BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of
- * the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that
- * enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Indicate whether or not a test case is using an in-vm broker.
- * <tr><td> Track which in-vm broker is currently in use.
- * <tr><td> Accept setting of a failure mechanism. <td> {@link CauseFailure}.
- * </table>
- *
- * @todo Need to think about how to present the brokers through this interface. Thinking numbering the available
- * brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto
- * 1 again?
- */
-public interface BrokerLifecycleAware
-{
- public void setInVmBrokers();
-
- /**
- * Indicates whether or not a test case is using in-vm brokers.
- *
- * @return <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise.
- */
- public boolean usingInVmBroker();
-
- /**
- * Sets the currently live in-vm broker.
- *
- * @param i The currently live in-vm broker.
- */
- public void setLiveBroker(int i);
-
- /**
- * Reports the currently live in-vm broker.
- *
- * @return The currently live in-vm broker.
- */
- public int getLiveBroker();
-
- /**
- * Accepts a failure mechanism.
- *
- * @param failureMechanism The failure mechanism.
- */
- public void setFailureMechanism(CauseFailure failureMechanism);
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * BrokerLifecycleAware is an awareness interface implemented by test cases that can run control the life-cycle of
+ * the brokers on which they run. Its purpose is to expose additional instrumentation of brokers during testing, that
+ * enables tests to use an automated failure mechanism to simulate broker failures, and to re-start failed brokers.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Indicate whether or not a test case is using an in-vm broker.
+ * <tr><td> Track which in-vm broker is currently in use.
+ * <tr><td> Accept setting of a failure mechanism. <td> {@link CauseFailure}.
+ * </table>
+ *
+ * @todo Need to think about how to present the brokers through this interface. Thinking numbering the available
+ * brokers from 1 will do. Then can kill 1 and assume failing onto 2. Restart 1 and kill 2 and fail back onto
+ * 1 again?
+ */
+public interface BrokerLifecycleAware
+{
+ public void setInVmBrokers();
+
+ /**
+ * Indicates whether or not a test case is using in-vm brokers.
+ *
+ * @return <tt>true</tt> if the test is using in-vm brokers, <tt>false</tt> otherwise.
+ */
+ public boolean usingInVmBroker();
+
+ /**
+ * Sets the currently live in-vm broker.
+ *
+ * @param i The currently live in-vm broker.
+ */
+ public void setLiveBroker(int i);
+
+ /**
+ * Reports the currently live in-vm broker.
+ *
+ * @return The currently live in-vm broker.
+ */
+ public int getLiveBroker();
+
+ /**
+ * Accepts a failure mechanism.
+ *
+ * @param failureMechanism The failure mechanism.
+ */
+ public void setFailureMechanism(CauseFailure failureMechanism);
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java
index 8a5a9560a0..9bdd5a72c5 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailure.java
@@ -1,42 +1,42 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-/**
- * CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over
- * or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker,
- * or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable
- * to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or
- * dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract
- * the exact cause and nature of a failure out of failure test cases.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities
- * <tr><td> Cause messaging broker failure.
- * </table>
- */
-public interface CauseFailure
-{
- /**
- * Causes the active message broker to fail.
- */
- void causeFailure();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * CauseFailure provides a method to cause a failure in a messaging broker, usually used in conjunction with fail-over
+ * or other failure mode testing. In some cases failures may be automated, for example by shutting down an in-vm broker,
+ * or by sending a special control signal to a broker over a network connection. In other cases, it may be preferable
+ * to ask a user interactively to cause a failure scenario, in which case an implementation may display a prompt or
+ * dialog box asking for notification once the failure has been caused. The purpose of this interface is to abstract
+ * the exact cause and nature of a failure out of failure test cases.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Cause messaging broker failure.
+ * </table>
+ */
+public interface CauseFailure
+{
+ /**
+ * Causes the active message broker to fail.
+ */
+ void causeFailure();
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java
index 6b96ade674..889df4ad07 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/CauseFailureUserPrompt.java
@@ -1,65 +1,65 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-import org.apache.qpid.test.framework.CauseFailure;
-
-import java.io.IOException;
-
-/**
- * Causes a message broker failure by interactively prompting the user to cause it.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Cause messaging broker failure.
- * </table>
- */
-public class CauseFailureUserPrompt implements CauseFailure
-{
- /**
- * Causes the active message broker to fail.
- */
- public void causeFailure()
- {
- waitForUser("Cause a broker failure now, then press Return.");
- }
-
- /**
- * Outputs a prompt to the console and waits for the user to press return.
- *
- * @param prompt The prompt to display on the console.
- */
- private void waitForUser(String prompt)
- {
- System.out.println(prompt);
-
- try
- {
- System.in.read();
- }
- catch (IOException e)
- {
- // Ignored.
- }
-
- System.out.println("Continuing.");
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.qpid.test.framework.CauseFailure;
+
+import java.io.IOException;
+
+/**
+ * Causes a message broker failure by interactively prompting the user to cause it.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Cause messaging broker failure.
+ * </table>
+ */
+public class CauseFailureUserPrompt implements CauseFailure
+{
+ /**
+ * Causes the active message broker to fail.
+ */
+ public void causeFailure()
+ {
+ waitForUser("Cause a broker failure now, then press Return.");
+ }
+
+ /**
+ * Outputs a prompt to the console and waits for the user to press return.
+ *
+ * @param prompt The prompt to display on the console.
+ */
+ private void waitForUser(String prompt)
+ {
+ System.out.println(prompt);
+
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ // Ignored.
+ }
+
+ System.out.println("Continuing.");
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java
index e7268db8eb..9a4668e86f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/FrameworkTestContext.java
@@ -1,48 +1,48 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-/**
- * A FrameworkTestContext provides context information to test code about the current test case being run; its name, its
- * parameters.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide the name of the current test case.
- * <tr><td> Provide the test parameters.
- * </table>
- */
-public interface FrameworkTestContext
-{
- /**
- * Reports the current test case name.
- *
- * @return The current test case name.
- */
- TestCaseVector getTestCaseVector();
-
- /**
- * Reports the current test case parameters.
- *
- * @return The current test case parameters.
- */
- MessagingTestConfigProperties getTestParameters();
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * A FrameworkTestContext provides context information to test code about the current test case being run; its name, its
+ * parameters.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide the name of the current test case.
+ * <tr><td> Provide the test parameters.
+ * </table>
+ */
+public interface FrameworkTestContext
+{
+ /**
+ * Reports the current test case name.
+ *
+ * @return The current test case name.
+ */
+ TestCaseVector getTestCaseVector();
+
+ /**
+ * Reports the current test case parameters.
+ *
+ * @return The current test case parameters.
+ */
+ MessagingTestConfigProperties getTestParameters();
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
index d1fcad9cc0..7fbef06265 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalAMQPCircuitFactory.java
@@ -1,168 +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.test.framework;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.test.framework.localcircuit.LocalAMQPPublisherImpl;
-import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.*;
-
-/**
- * LocalAMQPCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
- * on the same JVM, allowing AMQP/Qpid specific options to be applied to the circuit.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a standard test procedure over a test circuit.
- * <tr><td> Construct test circuits appropriate to a tests context.
- * <tr><td> Construct test circuits the support AMQP specific options.
- * </table>
- */
-public class LocalAMQPCircuitFactory extends LocalCircuitFactory
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(LocalAMQPCircuitFactory.class);
-
- /**
- * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the publishing side of a test circuit.
- *
- * @throws javax.jms.JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageProducer producer =
- props.getPublisherProducerBind()
- ? ((props.getImmediate() | props.getMandatory())
- ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate())
- : session.createProducer(destination)) : null;
-
- MessageConsumer consumer =
- props.getPublisherConsumerBind()
- ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
- connection.setExceptionListener(exceptionMonitor);
-
- if (!props.getPublisherConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
- }
-
- /**
- * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the receiving side of a test circuit.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
-
- MessageProducer producer =
- props.getReceiverProducerBind()
- ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageConsumer consumer =
- props.getReceiverConsumerBind()
- ? ((props.getDurableSubscription() && props.getPubsub())
- ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
- : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- if (!props.getReceiverConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
- }
-
- /**
- * Creates a local {@link Publisher} from a {@link CircuitEnd}. The publisher implementation provides AMQP
- * specific assertion methods, for testing beyond JMS.
- *
- * @param publisherEnd The publishing circuit end.
- *
- * @return A {@link Receiver}.
- */
- protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
- {
- return new LocalAMQPPublisherImpl(publisherEnd);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.test.framework.localcircuit.LocalAMQPPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+/**
+ * LocalAMQPCircuitFactory is a test sequencer that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM, allowing AMQP/Qpid specific options to be applied to the circuit.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * <tr><td> Construct test circuits the support AMQP specific options.
+ * </table>
+ */
+public class LocalAMQPCircuitFactory extends LocalCircuitFactory
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(LocalAMQPCircuitFactory.class);
+
+ /**
+ * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the publishing side of a test circuit.
+ *
+ * @throws javax.jms.JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer =
+ props.getPublisherProducerBind()
+ ? ((props.getImmediate() | props.getMandatory())
+ ? ((AMQSession) session).createProducer(destination, props.getMandatory(), props.getImmediate())
+ : session.createProducer(destination)) : null;
+
+ MessageConsumer consumer =
+ props.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!props.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the receiving side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ MessageProducer producer =
+ props.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ props.getReceiverConsumerBind()
+ ? ((props.getDurableSubscription() && props.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!props.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /**
+ * Creates a local {@link Publisher} from a {@link CircuitEnd}. The publisher implementation provides AMQP
+ * specific assertion methods, for testing beyond JMS.
+ *
+ * @param publisherEnd The publishing circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalAMQPPublisherImpl(publisherEnd);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
index 38a924a4ee..68aad6ee47 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/LocalCircuitFactory.java
@@ -1,316 +1,316 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
-import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
-import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-import org.apache.qpid.util.ConversationFactory;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.*;
-
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
- * on the same JVM. The ends of the circuit are presented as {@link Publisher} and {@link Receiver} interfaces, which
- * in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
- * of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
- * use messaging features not available in JMS can be written. This provides an extension point for writing tests
- * against proprietary features of JMS implementations.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Provide a standard test procedure over a test circuit.
- * <tr><td> Construct test circuits appropriate to a tests context.
- * </table>
- */
-public class LocalCircuitFactory implements CircuitFactory
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(LocalCircuitFactory.class);
-
- /** Used to create unique destination names for each test. */
- protected static AtomicLong uniqueDestsId = new AtomicLong();
-
- /**
- * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
- * begining the test and gathering the test reports from the participants.
- *
- * @param testCircuit The test circuit.
- * @param assertions The list of assertions to apply to the test circuit.
- * @param testProperties The test case definition.
- */
- public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
- {
- FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions));
- }
-
- /**
- * Creates a test circuit for the test, configered by the test parameters specified.
- *
- * @param testProperties The test parameters.
- *
- * @return A test circuit.
- */
- public Circuit createCircuit(ParsedProperties testProperties)
- {
- Circuit result;
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
-
- // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
- try
- {
- // Get a unique offset to append to destination names to make them unique to the connection.
- long uniqueId = uniqueDestsId.incrementAndGet();
-
- // Set up the connection.
- Connection connection = TestUtils.createConnection(testProperties);
-
- // Add the connection exception listener to assert on exception conditions with.
- // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
- // connection.setExceptionListener(exceptionMonitor);
-
- // Set up the publisher.
- CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
-
- // Set up the receiver.
- CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
-
- // Start listening for incoming messages.
- connection.start();
-
- // Package everything up.
- LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
- LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
-
- result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
- }
- catch (JMSException e)
- {
- throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
- }
-
- return result;
- }
-
- /**
- * Creates a local {@link Receiver} from a {@link CircuitEnd}. Sub-classes may override this to provide more
- * specialized receivers if necessary.
- *
- * @param receiverEnd The receiving circuit end.
- *
- * @return A {@link Receiver}.
- */
- protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
- {
- return new LocalReceiverImpl(receiverEnd);
- }
-
- /**
- * Creates a local {@link Publisher} from a {@link CircuitEnd}. Sub-classes may override this to provide more
- * specialized receivers if necessary.
- *
- * @param publisherEnd The publishing circuit end.
- *
- * @return A {@link Receiver}.
- */
- protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
- {
- return new LocalPublisherImpl(publisherEnd);
- }
-
- /**
- * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the publishing side of a test circuit.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
- if (props.getImmediate() || props.getMandatory())
- {
- throw new RuntimeException(
- "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
- }
-
- Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null;
-
- MessageConsumer consumer =
- props.getPublisherConsumerBind()
- ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
- connection.setExceptionListener(exceptionMonitor);
-
- if (!props.getPublisherConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
- }
-
- /**
- * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
- *
- * @param connection The connection to build the circuit end on.
- * @param testProps The test parameters to configure the circuit end construction.
- * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
- *
- * @return A circuit end suitable for the receiving side of a test circuit.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
- */
- public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
- throws JMSException
- {
- log.debug(
- "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
- + uniqueId + "): called");
-
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
-
- // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
- if (props.getImmediate() || props.getMandatory())
- {
- throw new RuntimeException(
- "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
- }
-
- Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
-
- MessageProducer producer =
- props.getReceiverProducerBind()
- ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
-
- Destination destination =
- props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
- : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
-
- MessageConsumer consumer =
- props.getReceiverConsumerBind()
- ? ((props.getDurableSubscription() && props.getPubsub())
- ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
- : null;
-
- MessageMonitor messageMonitor = new MessageMonitor();
-
- if (consumer != null)
- {
- consumer.setMessageListener(messageMonitor);
- }
-
- if (!props.getReceiverConsumerActive() && (consumer != null))
- {
- consumer.close();
- }
-
- return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
- }
-
- /**
- * Sets the sender test client to coordinate the test with.
- *
- * @param sender The contact details of the sending client in the test.
- */
- public void setSender(TestClientDetails sender)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Sets the receiving test client to coordinate the test with.
- *
- * @param receiver The contact details of the sending client in the test.
- */
- public void setReceiver(TestClientDetails receiver)
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Supplies the sending test client.
- *
- * @return The sending test client.
- */
- public TestClientDetails getSender()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Supplies the receiving test client.
- *
- * @return The receiving test client.
- */
- public List<TestClientDetails> getReceivers()
- {
- throw new RuntimeException("Not implemented.");
- }
-
- /**
- * Accepts the conversation factory over which to hold the test coordinating conversation.
- *
- * @param conversationFactory The conversation factory to coordinate the test over.
- */
- public void setConversationFactory(ConversationFactory conversationFactory)
- {
- throw new RuntimeException("Not implemented.");
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalPublisherImpl;
+import org.apache.qpid.test.framework.localcircuit.LocalReceiverImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+import org.apache.qpid.util.ConversationFactory;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.*;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * LocalCircuitFactory is a circuit factory that creates test circuits with publishing and receiving ends rooted
+ * on the same JVM. The ends of the circuit are presented as {@link Publisher} and {@link Receiver} interfaces, which
+ * in turn provide methods to apply assertions to the circuit. The creation of the circuit ends, and the presentation
+ * of the ends as publisher/receiver interfaces, are designed to be overriden, so that circuits and assertions that
+ * use messaging features not available in JMS can be written. This provides an extension point for writing tests
+ * against proprietary features of JMS implementations.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a standard test procedure over a test circuit.
+ * <tr><td> Construct test circuits appropriate to a tests context.
+ * </table>
+ */
+public class LocalCircuitFactory implements CircuitFactory
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(LocalCircuitFactory.class);
+
+ /** Used to create unique destination names for each test. */
+ protected static AtomicLong uniqueDestsId = new AtomicLong();
+
+ /**
+ * Holds a test coordinating conversation with the test clients. This should consist of assigning the test roles,
+ * begining the test and gathering the test reports from the participants.
+ *
+ * @param testCircuit The test circuit.
+ * @param assertions The list of assertions to apply to the test circuit.
+ * @param testProperties The test case definition.
+ */
+ public void sequenceTest(Circuit testCircuit, List<Assertion> assertions, Properties testProperties)
+ {
+ FrameworkBaseCase.assertNoFailures(testCircuit.test(1, assertions));
+ }
+
+ /**
+ * Creates a test circuit for the test, configered by the test parameters specified.
+ *
+ * @param testProperties The test parameters.
+ *
+ * @return A test circuit.
+ */
+ public Circuit createCircuit(ParsedProperties testProperties)
+ {
+ Circuit result;
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ // Create a standard publisher/receivers test client pair on a shared connection, individual sessions.
+ try
+ {
+ // Get a unique offset to append to destination names to make them unique to the connection.
+ long uniqueId = uniqueDestsId.incrementAndGet();
+
+ // Set up the connection.
+ Connection connection = TestUtils.createConnection(testProperties);
+
+ // Add the connection exception listener to assert on exception conditions with.
+ // ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ // connection.setExceptionListener(exceptionMonitor);
+
+ // Set up the publisher.
+ CircuitEndBase publisherEnd = createPublisherCircuitEnd(connection, props, uniqueId);
+
+ // Set up the receiver.
+ CircuitEndBase receiverEnd = createReceiverCircuitEnd(connection, props, uniqueId);
+
+ // Start listening for incoming messages.
+ connection.start();
+
+ // Package everything up.
+ LocalPublisherImpl publisher = createPublisherFromCircuitEnd(publisherEnd);
+ LocalReceiverImpl receiver = createReceiverFromCircuitEnd(receiverEnd);
+
+ result = new LocalCircuitImpl(testProperties, publisher, receiver, connection, publisher.getExceptionMonitor());
+ }
+ catch (JMSException e)
+ {
+ throw new RuntimeException("Could not create publisher/receivers pair due to a JMSException.", e);
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a local {@link Receiver} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+ * specialized receivers if necessary.
+ *
+ * @param receiverEnd The receiving circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalReceiverImpl createReceiverFromCircuitEnd(CircuitEndBase receiverEnd)
+ {
+ return new LocalReceiverImpl(receiverEnd);
+ }
+
+ /**
+ * Creates a local {@link Publisher} from a {@link CircuitEnd}. Sub-classes may override this to provide more
+ * specialized receivers if necessary.
+ *
+ * @param publisherEnd The publishing circuit end.
+ *
+ * @return A {@link Receiver}.
+ */
+ protected LocalPublisherImpl createPublisherFromCircuitEnd(CircuitEndBase publisherEnd)
+ {
+ return new LocalPublisherImpl(publisherEnd);
+ }
+
+ /**
+ * Builds a circuit end suitable for the publishing side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the publishing side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createPublisherCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageProducer producer = props.getPublisherProducerBind() ? session.createProducer(destination) : null;
+
+ MessageConsumer consumer =
+ props.getPublisherConsumerBind()
+ ? session.createConsumer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ ExceptionMonitor exceptionMonitor = new ExceptionMonitor();
+ connection.setExceptionListener(exceptionMonitor);
+
+ if (!props.getPublisherConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Builds a circuit end suitable for the receiving side of a test circuit, from standard test parameters.
+ *
+ * @param connection The connection to build the circuit end on.
+ * @param testProps The test parameters to configure the circuit end construction.
+ * @param uniqueId A unique number to being numbering destinations from, to make this circuit unique.
+ *
+ * @return A circuit end suitable for the receiving side of a test circuit.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through and fail the creation.
+ */
+ public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId)
+ throws JMSException
+ {
+ log.debug(
+ "public CircuitEndBase createReceiverCircuitEnd(Connection connection, ParsedProperties testProps, long uniqueId = "
+ + uniqueId + "): called");
+
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProps);
+
+ // Check that the test properties do not contain AMQP/Qpid specific settings, and fail if they do.
+ if (props.getImmediate() || props.getMandatory())
+ {
+ throw new RuntimeException(
+ "Cannot create a pure JMS circuit as the test properties require AMQP specific options.");
+ }
+
+ Session session = connection.createSession(props.getPublisherTransacted(), props.getAckMode());
+
+ MessageProducer producer =
+ props.getReceiverProducerBind()
+ ? session.createProducer(session.createQueue(props.getReceiveDestinationNameRoot() + "_" + uniqueId)) : null;
+
+ Destination destination =
+ props.getPubsub() ? session.createTopic(props.getSendDestinationNameRoot() + "_" + uniqueId)
+ : session.createQueue(props.getSendDestinationNameRoot() + "_" + uniqueId);
+
+ MessageConsumer consumer =
+ props.getReceiverConsumerBind()
+ ? ((props.getDurableSubscription() && props.getPubsub())
+ ? session.createDurableSubscriber((Topic) destination, "testsub") : session.createConsumer(destination))
+ : null;
+
+ MessageMonitor messageMonitor = new MessageMonitor();
+
+ if (consumer != null)
+ {
+ consumer.setMessageListener(messageMonitor);
+ }
+
+ if (!props.getReceiverConsumerActive() && (consumer != null))
+ {
+ consumer.close();
+ }
+
+ return new CircuitEndBase(producer, consumer, session, messageMonitor, null);
+ }
+
+ /**
+ * Sets the sender test client to coordinate the test with.
+ *
+ * @param sender The contact details of the sending client in the test.
+ */
+ public void setSender(TestClientDetails sender)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Sets the receiving test client to coordinate the test with.
+ *
+ * @param receiver The contact details of the sending client in the test.
+ */
+ public void setReceiver(TestClientDetails receiver)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Supplies the sending test client.
+ *
+ * @return The sending test client.
+ */
+ public TestClientDetails getSender()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Supplies the receiving test client.
+ *
+ * @return The receiving test client.
+ */
+ public List<TestClientDetails> getReceivers()
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+
+ /**
+ * Accepts the conversation factory over which to hold the test coordinating conversation.
+ *
+ * @param conversationFactory The conversation factory to coordinate the test over.
+ */
+ public void setConversationFactory(ConversationFactory conversationFactory)
+ {
+ throw new RuntimeException("Not implemented.");
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java
index b672b9c3ce..397c4e9fbd 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/MessageIdentityVector.java
@@ -1,167 +1,167 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-/**
- * MessageIdentityVector provides a message identification scheme, that matches individual messages with test cases.
- * Test messages are being sent by a number of test clients, sending messages over a set of routes, and being received
- * by another set of test clients. Each test is itself, being run within a test cycle, of which there could be many. It
- * is the job of the test coordinator to request and receive reports from the available test clients, on what has been
- * sent, what has been received, and what errors may have occurred, and to reconcile this information against the
- * assertions being applied by the test case. In order to be able to figure out which messages belong to which test,
- * there needs to be an identification scheme, that the coordinator can use to correlate messages in senders and
- * receiver reports. Every message sent in a test can be associated with this information.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Identify a test case, a handling client id, a circuit end within the client, and a test cycle number.
- * </table>
- */
-public class MessageIdentityVector
-{
- /** Holds the test case vector component of the message identity vector. */
- private TestCaseVector testCaseVector;
-
- /** The unique client id. */
- private String clientId;
-
- /** The unique circuit end number within the client id. */
- private int circuitEndId;
-
- /**
- * Creates a new identity vector for test messages.
- *
- * @param testCase The name of the test case generating the messages.
- * @param clientId The unique id of the client implementing a circuit end that is handling the messages.
- * @param circuitEndId The unique id number of the circuit end within the client.
- * @param testCycleNumber The cycle iteration number of the test case.
- */
- public MessageIdentityVector(String testCase, String clientId, int circuitEndId, int testCycleNumber)
- {
- this.testCaseVector = new TestCaseVector(testCase, testCycleNumber);
- this.clientId = clientId;
- this.circuitEndId = circuitEndId;
- }
-
- /**
- * Reports the test case vector component of the message identity vector.
- *
- * @return The test case vector component of the message identity vector.
- */
- public TestCaseVector getTestCaseVector()
- {
- return testCaseVector;
- }
-
- /**
- * Reports the name of the test case.
- *
- * @return The name of the test case.
- */
- public String getTestCase()
- {
- return testCaseVector.getTestCase();
- }
-
- /**
- * Reports the test iteration cycle number within the test case.
- *
- * @return The test iteration cycle number within the test case.
- */
- public int getTestCycleNumber()
- {
- return testCaseVector.getTestCycleNumber();
- }
-
- /**
- * Resports the client id.
- *
- * @return The client id.
- */
- public String getClientId()
- {
- return clientId;
- }
-
- /**
- * Reports the circuit end number within the test client.
- *
- * @return The circuit end number within the test client.
- */
- public int getCircuitEndId()
- {
- return circuitEndId;
- }
-
- /**
- * Compares this identity vector with another for equality. All fields must match.
- *
- * @param o The identity vector to compare with.
- *
- * @return <tt>true</tt> if the identity vector is identical to this one by all fields, <tt>false</tt> otherwise.
- */
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if ((o == null) || (getClass() != o.getClass()))
- {
- return false;
- }
-
- MessageIdentityVector that = (MessageIdentityVector) o;
-
- if (circuitEndId != that.circuitEndId)
- {
- return false;
- }
-
- if ((clientId != null) ? (!clientId.equals(that.clientId)) : (that.clientId != null))
- {
- return false;
- }
-
- if ((testCaseVector != null) ? (!testCaseVector.equals(that.testCaseVector)) : (that.testCaseVector != null))
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Computes a hash code for this identity vector based on all fields.
- *
- * @return A hash code for this identity vector based on all fields.
- */
- public int hashCode()
- {
- int result;
- result = ((testCaseVector != null) ? testCaseVector.hashCode() : 0);
- result = (31 * result) + ((clientId != null) ? clientId.hashCode() : 0);
- result = (31 * result) + circuitEndId;
-
- return result;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * MessageIdentityVector provides a message identification scheme, that matches individual messages with test cases.
+ * Test messages are being sent by a number of test clients, sending messages over a set of routes, and being received
+ * by another set of test clients. Each test is itself, being run within a test cycle, of which there could be many. It
+ * is the job of the test coordinator to request and receive reports from the available test clients, on what has been
+ * sent, what has been received, and what errors may have occurred, and to reconcile this information against the
+ * assertions being applied by the test case. In order to be able to figure out which messages belong to which test,
+ * there needs to be an identification scheme, that the coordinator can use to correlate messages in senders and
+ * receiver reports. Every message sent in a test can be associated with this information.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Identify a test case, a handling client id, a circuit end within the client, and a test cycle number.
+ * </table>
+ */
+public class MessageIdentityVector
+{
+ /** Holds the test case vector component of the message identity vector. */
+ private TestCaseVector testCaseVector;
+
+ /** The unique client id. */
+ private String clientId;
+
+ /** The unique circuit end number within the client id. */
+ private int circuitEndId;
+
+ /**
+ * Creates a new identity vector for test messages.
+ *
+ * @param testCase The name of the test case generating the messages.
+ * @param clientId The unique id of the client implementing a circuit end that is handling the messages.
+ * @param circuitEndId The unique id number of the circuit end within the client.
+ * @param testCycleNumber The cycle iteration number of the test case.
+ */
+ public MessageIdentityVector(String testCase, String clientId, int circuitEndId, int testCycleNumber)
+ {
+ this.testCaseVector = new TestCaseVector(testCase, testCycleNumber);
+ this.clientId = clientId;
+ this.circuitEndId = circuitEndId;
+ }
+
+ /**
+ * Reports the test case vector component of the message identity vector.
+ *
+ * @return The test case vector component of the message identity vector.
+ */
+ public TestCaseVector getTestCaseVector()
+ {
+ return testCaseVector;
+ }
+
+ /**
+ * Reports the name of the test case.
+ *
+ * @return The name of the test case.
+ */
+ public String getTestCase()
+ {
+ return testCaseVector.getTestCase();
+ }
+
+ /**
+ * Reports the test iteration cycle number within the test case.
+ *
+ * @return The test iteration cycle number within the test case.
+ */
+ public int getTestCycleNumber()
+ {
+ return testCaseVector.getTestCycleNumber();
+ }
+
+ /**
+ * Resports the client id.
+ *
+ * @return The client id.
+ */
+ public String getClientId()
+ {
+ return clientId;
+ }
+
+ /**
+ * Reports the circuit end number within the test client.
+ *
+ * @return The circuit end number within the test client.
+ */
+ public int getCircuitEndId()
+ {
+ return circuitEndId;
+ }
+
+ /**
+ * Compares this identity vector with another for equality. All fields must match.
+ *
+ * @param o The identity vector to compare with.
+ *
+ * @return <tt>true</tt> if the identity vector is identical to this one by all fields, <tt>false</tt> otherwise.
+ */
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if ((o == null) || (getClass() != o.getClass()))
+ {
+ return false;
+ }
+
+ MessageIdentityVector that = (MessageIdentityVector) o;
+
+ if (circuitEndId != that.circuitEndId)
+ {
+ return false;
+ }
+
+ if ((clientId != null) ? (!clientId.equals(that.clientId)) : (that.clientId != null))
+ {
+ return false;
+ }
+
+ if ((testCaseVector != null) ? (!testCaseVector.equals(that.testCaseVector)) : (that.testCaseVector != null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Computes a hash code for this identity vector based on all fields.
+ *
+ * @return A hash code for this identity vector based on all fields.
+ */
+ public int hashCode()
+ {
+ int result;
+ result = ((testCaseVector != null) ? testCaseVector.hashCode() : 0);
+ result = (31 * result) + ((clientId != null) ? clientId.hashCode() : 0);
+ result = (31 * result) + circuitEndId;
+
+ return result;
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
index 63c7fd61c3..2a20be12d6 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/NotApplicableAssertion.java
@@ -1,112 +1,112 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-/**
- * NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
- * applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
- * being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
- * instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
- * as warnings to the console, or raise them as test failures.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Quitely pass.
- * <tr><td> Log a warning.
- * <tr><td> Raise a test failure.
- * </table>
- */
-public class NotApplicableAssertion implements Assertion
-{
- /** Used for logging to the console. */
- private static final Logger console = Logger.getLogger("CONSOLE." + NotApplicableAssertion.class.getName());
-
- /** The possible behavioural modes of this assertion. */
- private enum Mode
- {
- /** Quietly ignore the assertion by passing. */
- Quiet,
-
- /** Ignore the assertion by passing but log a warning about it. */
- Warn,
-
- /** Fail the assertion. */
- Fail;
- }
-
- /** The behavioural mode of the assertion. */
- private Mode mode;
-
- /**
- * Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
- * configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
- * read as 'fail'.
- *
- * @param testProperties The test configuration properties.
- */
- public NotApplicableAssertion(ParsedProperties testProperties)
- {
- // Cast the test properties into a typed interface for convenience.
- MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
-
- String modeName = props.getNotApplicableAssertionMode();
-
- if ("quiet".equals(modeName))
- {
- mode = Mode.Quiet;
- }
- else if ("warn".equals(modeName))
- {
- mode = Mode.Warn;
- }
- else
- {
- mode = Mode.Fail;
- }
- }
-
- /**
- * Applies the assertion.
- *
- * @return <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails.
- */
- public boolean apply()
- {
- switch (mode)
- {
- case Quiet:
- return true;
-
- case Warn:
- console.warn("Warning: Not applicable assertion being ignored.");
-
- return true;
-
- case Fail:
- default:
- return false;
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+/**
+ * NotApplicableAssertion is a messaging assertion that can be used when an assertion requested by a test-case is not
+ * applicable to the testing scenario. For example an assertion may relate to AMQP functionality, but a test case may be
+ * being run over a non-AMQP JMS implementation, in which case the request to create the assertion may return this
+ * instead of the proper assertion. The test framework is configurable to quietly drop these assertions, log them
+ * as warnings to the console, or raise them as test failures.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Quitely pass.
+ * <tr><td> Log a warning.
+ * <tr><td> Raise a test failure.
+ * </table>
+ */
+public class NotApplicableAssertion implements Assertion
+{
+ /** Used for logging to the console. */
+ private static final Logger console = Logger.getLogger("CONSOLE." + NotApplicableAssertion.class.getName());
+
+ /** The possible behavioural modes of this assertion. */
+ private enum Mode
+ {
+ /** Quietly ignore the assertion by passing. */
+ Quiet,
+
+ /** Ignore the assertion by passing but log a warning about it. */
+ Warn,
+
+ /** Fail the assertion. */
+ Fail;
+ }
+
+ /** The behavioural mode of the assertion. */
+ private Mode mode;
+
+ /**
+ * Creates an assertion that is driven by the value of the 'notApplicableAssertion' property of the test
+ * configuration. Its value should match one of 'quiet', 'warn' or 'fail' and if it does not it is automatically
+ * read as 'fail'.
+ *
+ * @param testProperties The test configuration properties.
+ */
+ public NotApplicableAssertion(ParsedProperties testProperties)
+ {
+ // Cast the test properties into a typed interface for convenience.
+ MessagingTestConfigProperties props = new MessagingTestConfigProperties(testProperties);
+
+ String modeName = props.getNotApplicableAssertionMode();
+
+ if ("quiet".equals(modeName))
+ {
+ mode = Mode.Quiet;
+ }
+ else if ("warn".equals(modeName))
+ {
+ mode = Mode.Warn;
+ }
+ else
+ {
+ mode = Mode.Fail;
+ }
+ }
+
+ /**
+ * Applies the assertion.
+ *
+ * @return <tt>true</tt> if the assertion passes, <tt>false</tt> if it fails.
+ */
+ public boolean apply()
+ {
+ switch (mode)
+ {
+ case Quiet:
+ return true;
+
+ case Warn:
+ console.warn("Warning: Not applicable assertion being ignored.");
+
+ return true;
+
+ case Fail:
+ default:
+ return false;
+ }
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java
index 0518a827ba..ad1e70f6f7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/TestCaseVector.java
@@ -1,88 +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.test.framework;
-
-/**
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- */
-public class TestCaseVector
-{
- /** The test case name. */
- private String testCase;
-
- /** The test cycle number within the test case. */
- private int testCycleNumber;
-
- public TestCaseVector(String testCase, int testCycleNumber)
- {
- this.testCase = testCase;
- this.testCycleNumber = testCycleNumber;
- }
-
- public String getTestCase()
- {
- return testCase;
- }
-
- public int getTestCycleNumber()
- {
- return testCycleNumber;
- }
-
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if ((o == null) || (getClass() != o.getClass()))
- {
- return false;
- }
-
- TestCaseVector that = (TestCaseVector) o;
-
- if (testCycleNumber != that.testCycleNumber)
- {
- return false;
- }
-
- if ((testCase != null) ? (!testCase.equals(that.testCase)) : (that.testCase != null))
- {
- return false;
- }
-
- return true;
- }
-
- public int hashCode()
- {
- int result;
- result = ((testCase != null) ? testCase.hashCode() : 0);
- result = (31 * result) + testCycleNumber;
-
- return result;
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class TestCaseVector
+{
+ /** The test case name. */
+ private String testCase;
+
+ /** The test cycle number within the test case. */
+ private int testCycleNumber;
+
+ public TestCaseVector(String testCase, int testCycleNumber)
+ {
+ this.testCase = testCase;
+ this.testCycleNumber = testCycleNumber;
+ }
+
+ public String getTestCase()
+ {
+ return testCase;
+ }
+
+ public int getTestCycleNumber()
+ {
+ return testCycleNumber;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if ((o == null) || (getClass() != o.getClass()))
+ {
+ return false;
+ }
+
+ TestCaseVector that = (TestCaseVector) o;
+
+ if (testCycleNumber != that.testCycleNumber)
+ {
+ return false;
+ }
+
+ if ((testCase != null) ? (!testCase.equals(that.testCase)) : (that.testCase != null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int result;
+ result = ((testCase != null) ? testCase.hashCode() : 0);
+ result = (31 * result) + testCycleNumber;
+
+ return result;
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
index 1c138fe575..9eba36e1e9 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/distributedtesting/TestClient.java
@@ -1,497 +1,497 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework.distributedtesting;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.NDC;
-
-import org.apache.qpid.test.framework.MessagingTestConfigProperties;
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.clocksynch.ClockSynchThread;
-import org.apache.qpid.test.framework.clocksynch.UDPClockSynchronizer;
-import org.apache.qpid.util.ReflectionUtils;
-import org.apache.qpid.util.ReflectionUtilsException;
-
-import org.apache.qpid.junit.extensions.SleepThrottle;
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-import javax.jms.*;
-
-import java.util.*;
-
-/**
- * Implements a test client as described in the interop testing spec
- * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
- * reacts to control message sequences send by the test {@link Coordinator}.
- *
- * <p/><table><caption>Messages Handled by TestClient</caption>
- * <tr><th> Message <th> Action
- * <tr><td> Invite(compulsory) <td> Reply with Enlist.
- * <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
- * <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches an enlisted test. Keep test parameters.
- * <tr><td> Start <td> Send test messages defined by test parameters. Send report on messages sent.
- * <tr><td> Status Request <td> Send report on messages received.
- * <tr><td> Terminate <td> Terminate the test client.
- * <tr><td> ClockSynch <td> Synch clock against the supplied UDP address.
- * </table>
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Handle all incoming control messages. <td> {@link TestClientControlledTest}
- * <tr><td> Configure and look up test cases by name. <td> {@link TestClientControlledTest}
- * </table>
- */
-public class TestClient implements MessageListener
-{
- /** Used for debugging. */
- private static final Logger log = Logger.getLogger(TestClient.class);
-
- /** Used for reporting to the console. */
- private static final Logger console = Logger.getLogger("CONSOLE");
-
- /** Holds the default identifying name of the test client. */
- public static final String CLIENT_NAME = "java";
-
- /** Holds the URL of the broker to run the tests on. */
- public static String brokerUrl;
-
- /** Holds the virtual host to run the tests on. If <tt>null</tt>, then the default virtual host is used. */
- public static String virtualHost;
-
- /**
- * Holds the test context properties that provides the default test parameters, plus command line overrides.
- * This is initialized with the default test parameters, to which command line overrides may be applied.
- */
- public static ParsedProperties testContextProperties =
- TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
-
- /** Holds all the test cases loaded from the classpath. */
- Map<String, TestClientControlledTest> testCases = new HashMap<String, TestClientControlledTest>();
-
- /** Holds the test case currently being run by this client. */
- protected TestClientControlledTest currentTestCase;
-
- /** Holds the connection to the broker that the test is being coordinated on. */
- protected Connection connection;
-
- /** Holds the message producer to hold the test coordination over. */
- protected MessageProducer producer;
-
- /** Holds the JMS controlSession for the test coordination. */
- protected Session session;
-
- /** Holds the name of this client, with a default value. */
- protected String clientName = CLIENT_NAME;
-
- /** This flag indicates that the test client should attempt to join the currently running test case on start up. */
- protected boolean join;
-
- /** Holds the clock synchronizer for the test node. */
- ClockSynchThread clockSynchThread;
-
- /**
- * Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client
- * identifying name.
- *
- * @param pBrokerUrl The url of the broker to connect to.
- * @param pVirtualHost The virtual host to conect to.
- * @param clientName The client name to use.
- * @param join Flag to indicate that this client should attempt to join running tests.
- */
- public TestClient(String pBrokerUrl, String pVirtualHost, String clientName, boolean join)
- {
- log.debug("public TestClient(String pBrokerUrl = " + pBrokerUrl + ", String pVirtualHost = " + pVirtualHost
- + ", String clientName = " + clientName + ", boolean join = " + join + "): called");
-
- // Retain the connection parameters.
- brokerUrl = pBrokerUrl;
- virtualHost = pVirtualHost;
- this.clientName = clientName;
- this.join = join;
- }
-
- /**
- * The entry point for the interop test coordinator. This client accepts the following command line arguments:
- *
- * <p/><table>
- * <tr><td> -b <td> The broker URL. <td> Optional.
- * <tr><td> -h <td> The virtual host. <td> Optional.
- * <tr><td> -n <td> The test client name. <td> Optional.
- * <tr><td> name=value <td> Trailing argument define name/value pairs. Added to system properties. <td> Optional.
- * </table>
- *
- * @param args The command line arguments.
- */
- public static void main(String[] args)
- {
- log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called");
- console.info("Qpid Distributed Test Client.");
-
- // Override the default broker url to be localhost:5672.
- testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
-
- // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
- // and usage then exist if there are errors).
- // Any options and trailing name=value pairs are also injected into the test context properties object,
- // to override any defaults that may have been set up.
- ParsedProperties options =
- new ParsedProperties(org.apache.qpid.junit.extensions.util.CommandLineParser.processCommandLine(args,
- new org.apache.qpid.junit.extensions.util.CommandLineParser(
- new String[][]
- {
- { "b", "The broker URL.", "broker", "false" },
- { "h", "The virtual host to use.", "virtual host", "false" },
- { "o", "The name of the directory to output test timings to.", "dir", "false" },
- { "n", "The name of the test client.", "name", "false" },
- { "j", "Join this test client to running test.", "false" }
- }), testContextProperties));
-
- // Extract the command line options.
- String brokerUrl = options.getProperty("b");
- String virtualHost = options.getProperty("h");
- String clientName = options.getProperty("n");
- clientName = (clientName == null) ? CLIENT_NAME : clientName;
- boolean join = options.getPropertyAsBoolean("j");
-
- // To distinguish logging output set up an NDC on the client name.
- NDC.push(clientName);
-
- // Create a test client and start it running.
- TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join);
-
- // Use a class path scanner to find all the interop test case implementations.
- // Hard code the test classes till the classpath scanner is fixed.
- Collection<Class<? extends TestClientControlledTest>> testCaseClasses =
- new ArrayList<Class<? extends TestClientControlledTest>>();
- // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true);
- testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun",
- "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P",
- "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub",
- "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize",
- "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize",
- "org.apache.qpid.test.framework.distributedcircuit.TestClientCircuitEnd"));
-
- try
- {
- client.start(testCaseClasses);
- }
- catch (Exception e)
- {
- log.error("The test client was unable to start.", e);
- console.info(e.getMessage());
- System.exit(1);
- }
- }
-
- /**
- * Parses a list of class names, and loads them if they are available on the class path.
- *
- * @param classNames The names of the classes to load.
- *
- * @return A list of the loaded test case classes.
- */
- public static List<Class<? extends TestClientControlledTest>> loadTestCases(String... classNames)
- {
- List<Class<? extends TestClientControlledTest>> testCases =
- new LinkedList<Class<? extends TestClientControlledTest>>();
-
- for (String className : classNames)
- {
- try
- {
- Class<?> cls = ReflectionUtils.forName(className);
- testCases.add((Class<? extends TestClientControlledTest>) cls);
- }
- catch (ReflectionUtilsException e)
- {
- // Ignore, class could not be found, so test not available.
- console.warn("Requested class " + className + " cannot be found, ignoring it.");
- }
- catch (ClassCastException e)
- {
- // Ignore, class was not of correct type to be a test case.
- console.warn("Requested class " + className + " is not an instance of TestClientControlledTest.");
- }
- }
-
- return testCases;
- }
-
- /**
- * Starts the interop test client running. This causes it to start listening for incoming test invites.
- *
- * @param testCaseClasses The classes of the available test cases. The test case names from these are used to
- * matchin incoming test invites against.
- *
- * @throws JMSException Any underlying JMSExceptions are allowed to fall through.
- */
- protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses) throws JMSException
- {
- log.debug("protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses = "
- + testCaseClasses + "): called");
-
- // Create all the test case implementations and index them by the test names.
- for (Class<? extends TestClientControlledTest> nextClass : testCaseClasses)
- {
- try
- {
- TestClientControlledTest testCase = nextClass.newInstance();
- testCases.put(testCase.getName(), testCase);
- }
- catch (InstantiationException e)
- {
- log.warn("Could not instantiate test case class: " + nextClass.getName(), e);
- // Ignored.
- }
- catch (IllegalAccessException e)
- {
- log.warn("Could not instantiate test case class due to illegal access: " + nextClass.getName(), e);
- // Ignored.
- }
- }
-
- // Open a connection to communicate with the coordinator on.
- connection = TestUtils.createConnection(testContextProperties);
- session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
- // Set this up to listen for control messages.
- Topic privateControlTopic = session.createTopic("iop.control." + clientName);
- MessageConsumer consumer = session.createConsumer(privateControlTopic);
- consumer.setMessageListener(this);
-
- Topic controlTopic = session.createTopic("iop.control");
- MessageConsumer consumer2 = session.createConsumer(controlTopic);
- consumer2.setMessageListener(this);
-
- // Create a producer to send replies with.
- producer = session.createProducer(null);
-
- // If the join flag was set, then broadcast a join message to notify the coordinator that a new test client
- // is available to join the current test case, if it supports it. This message may be ignored, or it may result
- // in this test client receiving a test invite.
- if (join)
- {
- Message joinMessage = session.createMessage();
-
- joinMessage.setStringProperty("CONTROL_TYPE", "JOIN");
- joinMessage.setStringProperty("CLIENT_NAME", clientName);
- joinMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
- producer.send(controlTopic, joinMessage);
- }
-
- // Start listening for incoming control messages.
- connection.start();
- }
-
- /**
- * Handles all incoming control messages.
- *
- * @param message The incoming message.
- */
- public void onMessage(Message message)
- {
- NDC.push(clientName);
- log.debug("public void onMessage(Message message = " + message + "): called");
-
- try
- {
- String controlType = message.getStringProperty("CONTROL_TYPE");
- String testName = message.getStringProperty("TEST_NAME");
-
- log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'");
-
- // Check if the message is a test invite.
- if ("INVITE".equals(controlType))
- {
- // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites
- // for which test cases exist.
- boolean enlist = false;
-
- if (testName != null)
- {
- log.debug("Got an invite to test: " + testName);
-
- // Check if the requested test case is available.
- TestClientControlledTest testCase = testCases.get(testName);
-
- if (testCase != null)
- {
- log.debug("Found implementing class for test '" + testName + "', enlisting for it.");
-
- // Check if the test case will accept the invitation.
- enlist = testCase.acceptInvite(message);
-
- log.debug("The test case "
- + (enlist ? " accepted the invite, enlisting for it."
- : " did not accept the invite, not enlisting."));
-
- // Make the requested test case the current test case.
- currentTestCase = testCase;
- }
- else
- {
- log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
- }
- }
- else
- {
- log.debug("Got a compulsory invite, enlisting for it.");
-
- enlist = true;
- }
-
- if (enlist)
- {
- // Reply with the client name in an Enlist message.
- Message enlistMessage = session.createMessage();
- enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST");
- enlistMessage.setStringProperty("CLIENT_NAME", clientName);
- enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
- enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
-
- log.debug("Sending enlist message '" + enlistMessage + "' to " + message.getJMSReplyTo());
-
- producer.send(message.getJMSReplyTo(), enlistMessage);
- }
- else
- {
- // Reply with the client name in an Decline message.
- Message enlistMessage = session.createMessage();
- enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE");
- enlistMessage.setStringProperty("CLIENT_NAME", clientName);
- enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
- enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
-
- log.debug("Sending decline message '" + enlistMessage + "' to " + message.getJMSReplyTo());
-
- producer.send(message.getJMSReplyTo(), enlistMessage);
- }
- }
- else if ("ASSIGN_ROLE".equals(controlType))
- {
- // Assign the role to the current test case.
- String roleName = message.getStringProperty("ROLE");
-
- log.debug("Got a role assignment to role: " + roleName);
-
- TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName);
-
- currentTestCase.assignRole(role, message);
-
- // Reply by accepting the role in an Accept Role message.
- Message acceptRoleMessage = session.createMessage();
- acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName);
- acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE");
- acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID());
-
- log.debug("Sending accept role message '" + acceptRoleMessage + "' to " + message.getJMSReplyTo());
-
- producer.send(message.getJMSReplyTo(), acceptRoleMessage);
- }
- else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType))
- {
- if ("START".equals(controlType))
- {
- log.debug("Got a start notification.");
-
- // Extract the number of test messages to send from the start notification.
- int numMessages;
-
- try
- {
- numMessages = message.getIntProperty("MESSAGE_COUNT");
- }
- catch (NumberFormatException e)
- {
- // If the number of messages is not specified, use the default of one.
- numMessages = 1;
- }
-
- // Start the current test case.
- currentTestCase.start(numMessages);
- }
- else
- {
- log.debug("Got a status request.");
- }
-
- // Generate the report from the test case and reply with it as a Report message.
- Message reportMessage = currentTestCase.getReport(session);
- reportMessage.setStringProperty("CLIENT_NAME", clientName);
- reportMessage.setStringProperty("CONTROL_TYPE", "REPORT");
- reportMessage.setJMSCorrelationID(message.getJMSCorrelationID());
-
- log.debug("Sending report message '" + reportMessage + "' to " + message.getJMSReplyTo());
-
- producer.send(message.getJMSReplyTo(), reportMessage);
- }
- else if ("TERMINATE".equals(controlType))
- {
- console.info("Received termination instruction from coordinator.");
-
- // Is a cleaner shutdown needed?
- connection.close();
- System.exit(0);
- }
- else if ("CLOCK_SYNCH".equals(controlType))
- {
- log.debug("Received clock synch command.");
- String address = message.getStringProperty("ADDRESS");
-
- log.debug("address = " + address);
-
- // Re-create (if necessary) and start the clock synch thread to synch the clock every ten seconds.
- if (clockSynchThread != null)
- {
- clockSynchThread.terminate();
- }
-
- SleepThrottle throttle = new SleepThrottle();
- throttle.setRate(0.1f);
-
- clockSynchThread = new ClockSynchThread(new UDPClockSynchronizer(address), throttle);
- clockSynchThread.start();
- }
- else
- {
- // Log a warning about this but otherwise ignore it.
- log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message);
- }
- }
- catch (JMSException e)
- {
- // Log a warning about this, but otherwise ignore it.
- log.warn("Got JMSException whilst handling message: " + message, e);
- }
- // Log any runtimes that fall through this message handler. These are fatal errors for the test client.
- catch (RuntimeException e)
- {
- log.error("The test client message handler got an unhandled exception: ", e);
- console.info("The message handler got an unhandled exception, terminating the test client.");
- System.exit(1);
- }
- finally
- {
- NDC.pop();
- }
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.distributedtesting;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.NDC;
+
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.clocksynch.ClockSynchThread;
+import org.apache.qpid.test.framework.clocksynch.UDPClockSynchronizer;
+import org.apache.qpid.util.ReflectionUtils;
+import org.apache.qpid.util.ReflectionUtilsException;
+
+import org.apache.qpid.junit.extensions.SleepThrottle;
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+import javax.jms.*;
+
+import java.util.*;
+
+/**
+ * Implements a test client as described in the interop testing spec
+ * (http://cwiki.apache.org/confluence/display/qpid/Interop+Testing+Specification). A test client is an agent that
+ * reacts to control message sequences send by the test {@link Coordinator}.
+ *
+ * <p/><table><caption>Messages Handled by TestClient</caption>
+ * <tr><th> Message <th> Action
+ * <tr><td> Invite(compulsory) <td> Reply with Enlist.
+ * <tr><td> Invite(test case) <td> Reply with Enlist if test case available.
+ * <tr><td> AssignRole(test case) <td> Reply with Accept Role if matches an enlisted test. Keep test parameters.
+ * <tr><td> Start <td> Send test messages defined by test parameters. Send report on messages sent.
+ * <tr><td> Status Request <td> Send report on messages received.
+ * <tr><td> Terminate <td> Terminate the test client.
+ * <tr><td> ClockSynch <td> Synch clock against the supplied UDP address.
+ * </table>
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Handle all incoming control messages. <td> {@link TestClientControlledTest}
+ * <tr><td> Configure and look up test cases by name. <td> {@link TestClientControlledTest}
+ * </table>
+ */
+public class TestClient implements MessageListener
+{
+ /** Used for debugging. */
+ private static final Logger log = Logger.getLogger(TestClient.class);
+
+ /** Used for reporting to the console. */
+ private static final Logger console = Logger.getLogger("CONSOLE");
+
+ /** Holds the default identifying name of the test client. */
+ public static final String CLIENT_NAME = "java";
+
+ /** Holds the URL of the broker to run the tests on. */
+ public static String brokerUrl;
+
+ /** Holds the virtual host to run the tests on. If <tt>null</tt>, then the default virtual host is used. */
+ public static String virtualHost;
+
+ /**
+ * Holds the test context properties that provides the default test parameters, plus command line overrides.
+ * This is initialized with the default test parameters, to which command line overrides may be applied.
+ */
+ public static ParsedProperties testContextProperties =
+ TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /** Holds all the test cases loaded from the classpath. */
+ Map<String, TestClientControlledTest> testCases = new HashMap<String, TestClientControlledTest>();
+
+ /** Holds the test case currently being run by this client. */
+ protected TestClientControlledTest currentTestCase;
+
+ /** Holds the connection to the broker that the test is being coordinated on. */
+ protected Connection connection;
+
+ /** Holds the message producer to hold the test coordination over. */
+ protected MessageProducer producer;
+
+ /** Holds the JMS controlSession for the test coordination. */
+ protected Session session;
+
+ /** Holds the name of this client, with a default value. */
+ protected String clientName = CLIENT_NAME;
+
+ /** This flag indicates that the test client should attempt to join the currently running test case on start up. */
+ protected boolean join;
+
+ /** Holds the clock synchronizer for the test node. */
+ ClockSynchThread clockSynchThread;
+
+ /**
+ * Creates a new interop test client, listenting to the specified broker and virtual host, with the specified client
+ * identifying name.
+ *
+ * @param pBrokerUrl The url of the broker to connect to.
+ * @param pVirtualHost The virtual host to conect to.
+ * @param clientName The client name to use.
+ * @param join Flag to indicate that this client should attempt to join running tests.
+ */
+ public TestClient(String pBrokerUrl, String pVirtualHost, String clientName, boolean join)
+ {
+ log.debug("public TestClient(String pBrokerUrl = " + pBrokerUrl + ", String pVirtualHost = " + pVirtualHost
+ + ", String clientName = " + clientName + ", boolean join = " + join + "): called");
+
+ // Retain the connection parameters.
+ brokerUrl = pBrokerUrl;
+ virtualHost = pVirtualHost;
+ this.clientName = clientName;
+ this.join = join;
+ }
+
+ /**
+ * The entry point for the interop test coordinator. This client accepts the following command line arguments:
+ *
+ * <p/><table>
+ * <tr><td> -b <td> The broker URL. <td> Optional.
+ * <tr><td> -h <td> The virtual host. <td> Optional.
+ * <tr><td> -n <td> The test client name. <td> Optional.
+ * <tr><td> name=value <td> Trailing argument define name/value pairs. Added to system properties. <td> Optional.
+ * </table>
+ *
+ * @param args The command line arguments.
+ */
+ public static void main(String[] args)
+ {
+ log.debug("public static void main(String[] args = " + Arrays.toString(args) + "): called");
+ console.info("Qpid Distributed Test Client.");
+
+ // Override the default broker url to be localhost:5672.
+ testContextProperties.setProperty(MessagingTestConfigProperties.BROKER_PROPNAME, "tcp://localhost:5672");
+
+ // Use the command line parser to evaluate the command line with standard handling behaviour (print errors
+ // and usage then exist if there are errors).
+ // Any options and trailing name=value pairs are also injected into the test context properties object,
+ // to override any defaults that may have been set up.
+ ParsedProperties options =
+ new ParsedProperties(org.apache.qpid.junit.extensions.util.CommandLineParser.processCommandLine(args,
+ new org.apache.qpid.junit.extensions.util.CommandLineParser(
+ new String[][]
+ {
+ { "b", "The broker URL.", "broker", "false" },
+ { "h", "The virtual host to use.", "virtual host", "false" },
+ { "o", "The name of the directory to output test timings to.", "dir", "false" },
+ { "n", "The name of the test client.", "name", "false" },
+ { "j", "Join this test client to running test.", "false" }
+ }), testContextProperties));
+
+ // Extract the command line options.
+ String brokerUrl = options.getProperty("b");
+ String virtualHost = options.getProperty("h");
+ String clientName = options.getProperty("n");
+ clientName = (clientName == null) ? CLIENT_NAME : clientName;
+ boolean join = options.getPropertyAsBoolean("j");
+
+ // To distinguish logging output set up an NDC on the client name.
+ NDC.push(clientName);
+
+ // Create a test client and start it running.
+ TestClient client = new TestClient(brokerUrl, virtualHost, clientName, join);
+
+ // Use a class path scanner to find all the interop test case implementations.
+ // Hard code the test classes till the classpath scanner is fixed.
+ Collection<Class<? extends TestClientControlledTest>> testCaseClasses =
+ new ArrayList<Class<? extends TestClientControlledTest>>();
+ // ClasspathScanner.getMatches(TestClientControlledTest.class, "^TestCase.*", true);
+ testCaseClasses.addAll(loadTestCases("org.apache.qpid.interop.clienttestcases.TestCase1DummyRun",
+ "org.apache.qpid.interop.clienttestcases.TestCase2BasicP2P",
+ "org.apache.qpid.interop.clienttestcases.TestCase3BasicPubSub",
+ "org.apache.qpid.interop.clienttestcases.TestCase4P2PMessageSize",
+ "org.apache.qpid.interop.clienttestcases.TestCase5PubSubMessageSize",
+ "org.apache.qpid.test.framework.distributedcircuit.TestClientCircuitEnd"));
+
+ try
+ {
+ client.start(testCaseClasses);
+ }
+ catch (Exception e)
+ {
+ log.error("The test client was unable to start.", e);
+ console.info(e.getMessage());
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Parses a list of class names, and loads them if they are available on the class path.
+ *
+ * @param classNames The names of the classes to load.
+ *
+ * @return A list of the loaded test case classes.
+ */
+ public static List<Class<? extends TestClientControlledTest>> loadTestCases(String... classNames)
+ {
+ List<Class<? extends TestClientControlledTest>> testCases =
+ new LinkedList<Class<? extends TestClientControlledTest>>();
+
+ for (String className : classNames)
+ {
+ try
+ {
+ Class<?> cls = ReflectionUtils.forName(className);
+ testCases.add((Class<? extends TestClientControlledTest>) cls);
+ }
+ catch (ReflectionUtilsException e)
+ {
+ // Ignore, class could not be found, so test not available.
+ console.warn("Requested class " + className + " cannot be found, ignoring it.");
+ }
+ catch (ClassCastException e)
+ {
+ // Ignore, class was not of correct type to be a test case.
+ console.warn("Requested class " + className + " is not an instance of TestClientControlledTest.");
+ }
+ }
+
+ return testCases;
+ }
+
+ /**
+ * Starts the interop test client running. This causes it to start listening for incoming test invites.
+ *
+ * @param testCaseClasses The classes of the available test cases. The test case names from these are used to
+ * matchin incoming test invites against.
+ *
+ * @throws JMSException Any underlying JMSExceptions are allowed to fall through.
+ */
+ protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses) throws JMSException
+ {
+ log.debug("protected void start(Collection<Class<? extends TestClientControlledTest>> testCaseClasses = "
+ + testCaseClasses + "): called");
+
+ // Create all the test case implementations and index them by the test names.
+ for (Class<? extends TestClientControlledTest> nextClass : testCaseClasses)
+ {
+ try
+ {
+ TestClientControlledTest testCase = nextClass.newInstance();
+ testCases.put(testCase.getName(), testCase);
+ }
+ catch (InstantiationException e)
+ {
+ log.warn("Could not instantiate test case class: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ catch (IllegalAccessException e)
+ {
+ log.warn("Could not instantiate test case class due to illegal access: " + nextClass.getName(), e);
+ // Ignored.
+ }
+ }
+
+ // Open a connection to communicate with the coordinator on.
+ connection = TestUtils.createConnection(testContextProperties);
+ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ // Set this up to listen for control messages.
+ Topic privateControlTopic = session.createTopic("iop.control." + clientName);
+ MessageConsumer consumer = session.createConsumer(privateControlTopic);
+ consumer.setMessageListener(this);
+
+ Topic controlTopic = session.createTopic("iop.control");
+ MessageConsumer consumer2 = session.createConsumer(controlTopic);
+ consumer2.setMessageListener(this);
+
+ // Create a producer to send replies with.
+ producer = session.createProducer(null);
+
+ // If the join flag was set, then broadcast a join message to notify the coordinator that a new test client
+ // is available to join the current test case, if it supports it. This message may be ignored, or it may result
+ // in this test client receiving a test invite.
+ if (join)
+ {
+ Message joinMessage = session.createMessage();
+
+ joinMessage.setStringProperty("CONTROL_TYPE", "JOIN");
+ joinMessage.setStringProperty("CLIENT_NAME", clientName);
+ joinMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ producer.send(controlTopic, joinMessage);
+ }
+
+ // Start listening for incoming control messages.
+ connection.start();
+ }
+
+ /**
+ * Handles all incoming control messages.
+ *
+ * @param message The incoming message.
+ */
+ public void onMessage(Message message)
+ {
+ NDC.push(clientName);
+ log.debug("public void onMessage(Message message = " + message + "): called");
+
+ try
+ {
+ String controlType = message.getStringProperty("CONTROL_TYPE");
+ String testName = message.getStringProperty("TEST_NAME");
+
+ log.debug("Received control of type '" + controlType + "' for the test '" + testName + "'");
+
+ // Check if the message is a test invite.
+ if ("INVITE".equals(controlType))
+ {
+ // Flag used to indicate that an enlist should be sent. Only enlist to compulsory invites or invites
+ // for which test cases exist.
+ boolean enlist = false;
+
+ if (testName != null)
+ {
+ log.debug("Got an invite to test: " + testName);
+
+ // Check if the requested test case is available.
+ TestClientControlledTest testCase = testCases.get(testName);
+
+ if (testCase != null)
+ {
+ log.debug("Found implementing class for test '" + testName + "', enlisting for it.");
+
+ // Check if the test case will accept the invitation.
+ enlist = testCase.acceptInvite(message);
+
+ log.debug("The test case "
+ + (enlist ? " accepted the invite, enlisting for it."
+ : " did not accept the invite, not enlisting."));
+
+ // Make the requested test case the current test case.
+ currentTestCase = testCase;
+ }
+ else
+ {
+ log.debug("Received an invite to the test '" + testName + "' but this test is not known.");
+ }
+ }
+ else
+ {
+ log.debug("Got a compulsory invite, enlisting for it.");
+
+ enlist = true;
+ }
+
+ if (enlist)
+ {
+ // Reply with the client name in an Enlist message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "ENLIST");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending enlist message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ else
+ {
+ // Reply with the client name in an Decline message.
+ Message enlistMessage = session.createMessage();
+ enlistMessage.setStringProperty("CONTROL_TYPE", "DECLINE");
+ enlistMessage.setStringProperty("CLIENT_NAME", clientName);
+ enlistMessage.setStringProperty("CLIENT_PRIVATE_CONTROL_KEY", "iop.control." + clientName);
+ enlistMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending decline message '" + enlistMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), enlistMessage);
+ }
+ }
+ else if ("ASSIGN_ROLE".equals(controlType))
+ {
+ // Assign the role to the current test case.
+ String roleName = message.getStringProperty("ROLE");
+
+ log.debug("Got a role assignment to role: " + roleName);
+
+ TestClientControlledTest.Roles role = Enum.valueOf(TestClientControlledTest.Roles.class, roleName);
+
+ currentTestCase.assignRole(role, message);
+
+ // Reply by accepting the role in an Accept Role message.
+ Message acceptRoleMessage = session.createMessage();
+ acceptRoleMessage.setStringProperty("CLIENT_NAME", clientName);
+ acceptRoleMessage.setStringProperty("CONTROL_TYPE", "ACCEPT_ROLE");
+ acceptRoleMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending accept role message '" + acceptRoleMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), acceptRoleMessage);
+ }
+ else if ("START".equals(controlType) || "STATUS_REQUEST".equals(controlType))
+ {
+ if ("START".equals(controlType))
+ {
+ log.debug("Got a start notification.");
+
+ // Extract the number of test messages to send from the start notification.
+ int numMessages;
+
+ try
+ {
+ numMessages = message.getIntProperty("MESSAGE_COUNT");
+ }
+ catch (NumberFormatException e)
+ {
+ // If the number of messages is not specified, use the default of one.
+ numMessages = 1;
+ }
+
+ // Start the current test case.
+ currentTestCase.start(numMessages);
+ }
+ else
+ {
+ log.debug("Got a status request.");
+ }
+
+ // Generate the report from the test case and reply with it as a Report message.
+ Message reportMessage = currentTestCase.getReport(session);
+ reportMessage.setStringProperty("CLIENT_NAME", clientName);
+ reportMessage.setStringProperty("CONTROL_TYPE", "REPORT");
+ reportMessage.setJMSCorrelationID(message.getJMSCorrelationID());
+
+ log.debug("Sending report message '" + reportMessage + "' to " + message.getJMSReplyTo());
+
+ producer.send(message.getJMSReplyTo(), reportMessage);
+ }
+ else if ("TERMINATE".equals(controlType))
+ {
+ console.info("Received termination instruction from coordinator.");
+
+ // Is a cleaner shutdown needed?
+ connection.close();
+ System.exit(0);
+ }
+ else if ("CLOCK_SYNCH".equals(controlType))
+ {
+ log.debug("Received clock synch command.");
+ String address = message.getStringProperty("ADDRESS");
+
+ log.debug("address = " + address);
+
+ // Re-create (if necessary) and start the clock synch thread to synch the clock every ten seconds.
+ if (clockSynchThread != null)
+ {
+ clockSynchThread.terminate();
+ }
+
+ SleepThrottle throttle = new SleepThrottle();
+ throttle.setRate(0.1f);
+
+ clockSynchThread = new ClockSynchThread(new UDPClockSynchronizer(address), throttle);
+ clockSynchThread.start();
+ }
+ else
+ {
+ // Log a warning about this but otherwise ignore it.
+ log.warn("Got an unknown control message, controlType = " + controlType + ", message = " + message);
+ }
+ }
+ catch (JMSException e)
+ {
+ // Log a warning about this, but otherwise ignore it.
+ log.warn("Got JMSException whilst handling message: " + message, e);
+ }
+ // Log any runtimes that fall through this message handler. These are fatal errors for the test client.
+ catch (RuntimeException e)
+ {
+ log.error("The test client message handler got an unhandled exception: ", e);
+ console.info("The message handler got an unhandled exception, terminating the test client.");
+ System.exit(1);
+ }
+ finally
+ {
+ NDC.pop();
+ }
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java
index 14ae108da8..4388c7fbd8 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/localcircuit/LocalAMQPPublisherImpl.java
@@ -1,133 +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.test.framework.localcircuit;
-
-import org.apache.qpid.client.AMQNoConsumersException;
-import org.apache.qpid.client.AMQNoRouteException;
-import org.apache.qpid.test.framework.*;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-
-/**
- * LocalAMQPPublisherImpl is an extension of {@link LocalPublisherImpl} that adds AMQP specific features. Specifically
- * extra assertions for AMQP features not available through generic JMS.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- */
-public class LocalAMQPPublisherImpl extends LocalPublisherImpl implements AMQPPublisher
-{
- /**
- * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
- * for messages and exceptions received by the circuit end.
- *
- * @param producer The message producer for the circuit end point.
- * @param consumer The message consumer for the circuit end point.
- * @param session The controlSession for the circuit end point.
- * @param messageMonitor The monitor to notify of all messages received by the circuit end.
- * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
- */
- public LocalAMQPPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
- MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
- {
- super(producer, consumer, session, messageMonitor, exceptionMonitor);
- }
-
- /**
- * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
- *
- * @param end The circuit end base implementation to take producers and consumers from.
- */
- public LocalAMQPPublisherImpl(CircuitEndBase end)
- {
- super(end);
- }
-
- /**
- * Provides an assertion that the publisher got a no consumers exception on every message.
- *
- * @param testProps The test configuration properties.
- *
- * @return An assertion that the publisher got a no consumers exception on every message.
- */
- public Assertion noConsumersAssertion(ParsedProperties testProps)
- {
- return new AssertionBase()
- {
- public boolean apply()
- {
- boolean passed = true;
- ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
-
- if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class))
- {
- passed = false;
-
- addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName()
- + " on the connection.\n");
- addError((connectionExceptionMonitor.size() > 0)
- ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
- : "Got no exceptions on the connection.");
- }
-
- return passed;
- }
- };
- }
-
- /**
- * Provides an assertion that the publisher got a no rout exception on every message.
- *
- * @param testProps The test configuration properties.
- *
- * @return An assertion that the publisher got a no rout exception on every message.
- */
- public Assertion noRouteAssertion(ParsedProperties testProps)
- {
- return new AssertionBase()
- {
- public boolean apply()
- {
- boolean passed = true;
- ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
-
- if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class))
- {
- passed = false;
-
- addError("Was expecting linked exception type " + AMQNoRouteException.class.getName()
- + " on the connection.\n");
- addError((connectionExceptionMonitor.size() > 0)
- ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
- : "Got no exceptions on the connection.");
- }
-
- return passed;
- }
- };
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.localcircuit;
+
+import org.apache.qpid.client.AMQNoConsumersException;
+import org.apache.qpid.client.AMQNoRouteException;
+import org.apache.qpid.test.framework.*;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+/**
+ * LocalAMQPPublisherImpl is an extension of {@link LocalPublisherImpl} that adds AMQP specific features. Specifically
+ * extra assertions for AMQP features not available through generic JMS.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ */
+public class LocalAMQPPublisherImpl extends LocalPublisherImpl implements AMQPPublisher
+{
+ /**
+ * Creates a circuit end point on the specified producer, consumer and controlSession. Monitors are also configured
+ * for messages and exceptions received by the circuit end.
+ *
+ * @param producer The message producer for the circuit end point.
+ * @param consumer The message consumer for the circuit end point.
+ * @param session The controlSession for the circuit end point.
+ * @param messageMonitor The monitor to notify of all messages received by the circuit end.
+ * @param exceptionMonitor The monitor to notify of all exceptions received by the circuit end.
+ */
+ public LocalAMQPPublisherImpl(MessageProducer producer, MessageConsumer consumer, Session session,
+ MessageMonitor messageMonitor, ExceptionMonitor exceptionMonitor)
+ {
+ super(producer, consumer, session, messageMonitor, exceptionMonitor);
+ }
+
+ /**
+ * Creates a circuit end point from the producer, consumer and controlSession in a circuit end base implementation.
+ *
+ * @param end The circuit end base implementation to take producers and consumers from.
+ */
+ public LocalAMQPPublisherImpl(CircuitEndBase end)
+ {
+ super(end);
+ }
+
+ /**
+ * Provides an assertion that the publisher got a no consumers exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no consumers exception on every message.
+ */
+ public Assertion noConsumersAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public boolean apply()
+ {
+ boolean passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoConsumersException.class))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + AMQNoConsumersException.class.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+
+ /**
+ * Provides an assertion that the publisher got a no rout exception on every message.
+ *
+ * @param testProps The test configuration properties.
+ *
+ * @return An assertion that the publisher got a no rout exception on every message.
+ */
+ public Assertion noRouteAssertion(ParsedProperties testProps)
+ {
+ return new AssertionBase()
+ {
+ public boolean apply()
+ {
+ boolean passed = true;
+ ExceptionMonitor connectionExceptionMonitor = circuit.getConnectionExceptionMonitor();
+
+ if (!connectionExceptionMonitor.assertOneJMSExceptionWithLinkedCause(AMQNoRouteException.class))
+ {
+ passed = false;
+
+ addError("Was expecting linked exception type " + AMQNoRouteException.class.getName()
+ + " on the connection.\n");
+ addError((connectionExceptionMonitor.size() > 0)
+ ? ("Actually got the following exceptions on the connection, " + connectionExceptionMonitor)
+ : "Got no exceptions on the connection.");
+ }
+
+ return passed;
+ }
+ };
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
index 4545e3c164..c11f75e742 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/AMQPFeatureDecorator.java
@@ -1,96 +1,96 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework.qpid;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import org.apache.qpid.test.framework.LocalAMQPCircuitFactory;
-
-import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
-
-/**
- * AMQPFeatureDecorator applies decorations to {@link FrameworkBaseCase} tests, so that they may use Qpid/AMQP specific
- * features, not available through JMS. For example, the immediate and mandatory flags. This decorator replaces the
- * standard test circuit factory on the base class with one that allows these features to be used.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Substitute the circuit factory with an AMQP/Qpid specific one.
- * </table>
- *
- * @todo This wrapper substitutes in a LocalAMQPCircuitFactory, which is fine for local tests. For distributed tests
- * the Fanout or Interop factories are substituted in by their decorators instead. These actually use
- * distributed circuit static create methods to build the circuits, which should actually be changed to a factory,
- * so that static methods do not need to be used. The distributed circuit creater delegates the circuit
- * construction to remote test nodes. This decorator should not be used with distributed tests, or should be made
- * aware of them, in which case it might ensure that an AMQP feature (implied already by other properties) flag
- * is passed out to the remote test nodes, and provide a mechansim for them to decorate their circuit creation
- * with AMQP features too. Add factory substituion/decoration mechansim for test clients, here or in a seperate
- * class.
- */
-public class AMQPFeatureDecorator extends WrappedSuiteTestDecorator
-{
- /** The test suite to run. */
- private Test test;
-
- /**
- * Creates a wrapped test test decorator from another one.
- *
- * @param test The test test.
- */
- public AMQPFeatureDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
- *
- * @param testResult The the results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- for (Test test : getAllUnderlyingTests())
- {
- if (test instanceof FrameworkBaseCase)
- {
- FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test;
- frameworkTest.setCircuitFactory(new LocalAMQPCircuitFactory());
- }
- }
-
- // Run the test.
- test.run(testResult);
- }
-
- /**
- * Prints the name of the test for debugging purposes.
- *
- * @return The name of the test.
- */
- public String toString()
- {
- return "AMQPFeatureDecorator: [test = \"" + test + "\"]";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.LocalAMQPCircuitFactory;
+
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * AMQPFeatureDecorator applies decorations to {@link FrameworkBaseCase} tests, so that they may use Qpid/AMQP specific
+ * features, not available through JMS. For example, the immediate and mandatory flags. This decorator replaces the
+ * standard test circuit factory on the base class with one that allows these features to be used.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Substitute the circuit factory with an AMQP/Qpid specific one.
+ * </table>
+ *
+ * @todo This wrapper substitutes in a LocalAMQPCircuitFactory, which is fine for local tests. For distributed tests
+ * the Fanout or Interop factories are substituted in by their decorators instead. These actually use
+ * distributed circuit static create methods to build the circuits, which should actually be changed to a factory,
+ * so that static methods do not need to be used. The distributed circuit creater delegates the circuit
+ * construction to remote test nodes. This decorator should not be used with distributed tests, or should be made
+ * aware of them, in which case it might ensure that an AMQP feature (implied already by other properties) flag
+ * is passed out to the remote test nodes, and provide a mechansim for them to decorate their circuit creation
+ * with AMQP features too. Add factory substituion/decoration mechansim for test clients, here or in a seperate
+ * class.
+ */
+public class AMQPFeatureDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test test decorator from another one.
+ *
+ * @param test The test test.
+ */
+ public AMQPFeatureDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ if (test instanceof FrameworkBaseCase)
+ {
+ FrameworkBaseCase frameworkTest = (FrameworkBaseCase) test;
+ frameworkTest.setCircuitFactory(new LocalAMQPCircuitFactory());
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "AMQPFeatureDecorator: [test = \"" + test + "\"]";
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java
index 3a048ac042..2708253d86 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureDecorator.java
@@ -1,95 +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.test.framework.qpid;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import org.apache.qpid.test.framework.BrokerLifecycleAware;
-import org.apache.qpid.test.framework.CauseFailureUserPrompt;
-
-import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
-
-/**
- * CauseFailureDecorator applies decorations to {@link BrokerLifecycleAware} tests, so that they may use different failure
- * mechanisms. It is capable of detecting when a test case uses in-vm brokers, and setting up an automatic failure
- * for those tests, so that the current live broker can be shut-down by test cases. For external brokers, automatic
- * failure could be implemented, for example by having a kill script. At the moment this sets up the failure to prompt
- * a user interactively to cause a failure, using {@link CauseFailureUserPrompt}.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Setup automatic failures for in-vm brokers. <td> {@link CauseFailureInVM}
- * <tr><td> Setup user generated failures for external brokers. <td> {@link CauseFailureUserPrompt}.
- * <tr><td>
- * </table>
- *
- * @todo Slight problem in that CauseFailureInVM is Qpid specific, whereas CauseFailureUserPrompt is not. Would like the
- * failure decorator to be non-qpid specific so that it can test failure of any JMS implementation too. Either pass
- * in class name of failure mechanism, set it up in the in-vm decorator instead of here but with prompt user as the
- * default for when the in-vm decorator is not used?
- */
-public class CauseFailureDecorator extends WrappedSuiteTestDecorator
-{
- /** The test suite to run. */
- private Test test;
-
- /**
- * Creates a wrapped test test decorator from another one.
- *
- * @param test The test test.
- */
- public CauseFailureDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
- *
- * @param testResult The the results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- for (Test test : getAllUnderlyingTests())
- {
- if (test instanceof BrokerLifecycleAware)
- {
- BrokerLifecycleAware failureTest = (BrokerLifecycleAware) test;
- failureTest.setFailureMechanism(new CauseFailureUserPrompt());
- }
- }
-
- // Run the test.
- test.run(testResult);
- }
-
- /**
- * Prints the name of the test for debugging purposes.
- *
- * @return The name of the test.
- */
- public String toString()
- {
- return "CauseFailureDecorator: [test = \"" + test + "\"]";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+import org.apache.qpid.test.framework.CauseFailureUserPrompt;
+
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * CauseFailureDecorator applies decorations to {@link BrokerLifecycleAware} tests, so that they may use different failure
+ * mechanisms. It is capable of detecting when a test case uses in-vm brokers, and setting up an automatic failure
+ * for those tests, so that the current live broker can be shut-down by test cases. For external brokers, automatic
+ * failure could be implemented, for example by having a kill script. At the moment this sets up the failure to prompt
+ * a user interactively to cause a failure, using {@link CauseFailureUserPrompt}.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Setup automatic failures for in-vm brokers. <td> {@link CauseFailureInVM}
+ * <tr><td> Setup user generated failures for external brokers. <td> {@link CauseFailureUserPrompt}.
+ * <tr><td>
+ * </table>
+ *
+ * @todo Slight problem in that CauseFailureInVM is Qpid specific, whereas CauseFailureUserPrompt is not. Would like the
+ * failure decorator to be non-qpid specific so that it can test failure of any JMS implementation too. Either pass
+ * in class name of failure mechanism, set it up in the in-vm decorator instead of here but with prompt user as the
+ * default for when the in-vm decorator is not used?
+ */
+public class CauseFailureDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test test decorator from another one.
+ *
+ * @param test The test test.
+ */
+ public CauseFailureDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with a LocalAMQPCircuitFactory. Only tests that extend FrameworkBaseCase are decorated.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ if (test instanceof BrokerLifecycleAware)
+ {
+ BrokerLifecycleAware failureTest = (BrokerLifecycleAware) test;
+ failureTest.setFailureMechanism(new CauseFailureUserPrompt());
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "CauseFailureDecorator: [test = \"" + test + "\"]";
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java
index b63ac43601..3e03ad0872 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/CauseFailureInVM.java
@@ -1,70 +1,70 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework.qpid;
-
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.test.framework.CauseFailure;
-import org.apache.qpid.test.framework.BrokerLifecycleAware;
-
-/**
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Cause messaging broker failure on the active in-vm broker.
- * <td> {@link TransportConnection}, {@link ApplicationRegistry}
- * </table>
- */
-public class CauseFailureInVM implements CauseFailure
-{
- /** Holds the in-vm broker instrumented test case to create failures for. */
- private BrokerLifecycleAware inVMTest;
-
- /**
- * Creates an automated failure mechanism for testing against in-vm brokers. The test to create the mechanism
- * for is specified, and as this failure is for in-vm brokers, the test must be {@link org.apache.qpid.test.framework.BrokerLifecycleAware}. The test
- * must also report that it is currently being run against an in-vm broker, and it is a runtime error if it is not,
- * as the creator of this failure mechanism should already have checked that it is.
- *
- * @param inVMTest The test case to create an automated failure mechanism for.
- */
- public CauseFailureInVM(BrokerLifecycleAware inVMTest)
- {
- // Check that the test is really using in-vm brokers.
- if (!inVMTest.usingInVmBroker())
- {
- throw new RuntimeException(
- "Cannot create in-vm broker failure mechanism for a test that is not using in-vm brokers.");
- }
-
- this.inVMTest = inVMTest;
- }
-
- /**
- * Causes the active message broker to fail.
- */
- public void causeFailure()
- {
- int liveBroker = inVMTest.getLiveBroker();
-
- TransportConnection.killVMBroker(liveBroker);
- ApplicationRegistry.remove(liveBroker);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.test.framework.CauseFailure;
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+
+/**
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Cause messaging broker failure on the active in-vm broker.
+ * <td> {@link TransportConnection}, {@link ApplicationRegistry}
+ * </table>
+ */
+public class CauseFailureInVM implements CauseFailure
+{
+ /** Holds the in-vm broker instrumented test case to create failures for. */
+ private BrokerLifecycleAware inVMTest;
+
+ /**
+ * Creates an automated failure mechanism for testing against in-vm brokers. The test to create the mechanism
+ * for is specified, and as this failure is for in-vm brokers, the test must be {@link org.apache.qpid.test.framework.BrokerLifecycleAware}. The test
+ * must also report that it is currently being run against an in-vm broker, and it is a runtime error if it is not,
+ * as the creator of this failure mechanism should already have checked that it is.
+ *
+ * @param inVMTest The test case to create an automated failure mechanism for.
+ */
+ public CauseFailureInVM(BrokerLifecycleAware inVMTest)
+ {
+ // Check that the test is really using in-vm brokers.
+ if (!inVMTest.usingInVmBroker())
+ {
+ throw new RuntimeException(
+ "Cannot create in-vm broker failure mechanism for a test that is not using in-vm brokers.");
+ }
+
+ this.inVMTest = inVMTest;
+ }
+
+ /**
+ * Causes the active message broker to fail.
+ */
+ public void causeFailure()
+ {
+ int liveBroker = inVMTest.getLiveBroker();
+
+ TransportConnection.killVMBroker(liveBroker);
+ ApplicationRegistry.remove(liveBroker);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
index bcf052ea06..e0fddb10b7 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/framework/qpid/InVMBrokerDecorator.java
@@ -1,135 +1,135 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.framework.qpid;
-
-import junit.framework.Test;
-import junit.framework.TestResult;
-
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.test.framework.BrokerLifecycleAware;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-
-import org.apache.qpid.junit.extensions.SetupTaskAware;
-import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
-
-/**
- * InVMBrokerDecorator is a test decorator, that is activated when running tests against an in-vm broker only. Its
- * purpose is to automatically create, and close and delete an in-vm broker, during the set-up and tear-down of
- * each test case. This decorator may only be used in conjunction with tests that extend {@link FrameworkBaseCase}.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Create/Destroy an in-vm broker on every test run.
- * </table>
- *
- * @todo May need to add a more fine grained injection point for the in-vm broker management, as this acts at the
- * suite level, rather than the individual test level.
- *
- * @todo Management of in-vm brokers for failure testing. Failure test setups may need to set their connection url to
- * use multiple broker (vm://:1;vm://:2), with fail-over between them. There is round-robin fail-over, but also
- * retry? A test case using an in-vm broker needs to record which one it is using, so that it can be
- * killed/restarted.
- */
-public class InVMBrokerDecorator extends WrappedSuiteTestDecorator
-{
- /** The test suite to run. */
- private Test test;
-
- /**
- * Creates a wrapped test suite decorator from another one.
- *
- * @param test The test suite.
- */
- public InVMBrokerDecorator(WrappedSuiteTestDecorator test)
- {
- super(test);
- this.test = test;
- }
-
- /**
- * Runs the tests with in-vm broker creation and clean-up added to the tests task stack.
- *
- * @param testResult The the results object to monitor the test results with.
- */
- public void run(TestResult testResult)
- {
- for (Test test : getAllUnderlyingTests())
- {
- // Check that the test to have an in-vm broker setup/teardown task added to it, is actually a framework
- // test that can handle setup tasks.
- if ((test instanceof SetupTaskAware))
- {
- SetupTaskAware frameworkTest = (SetupTaskAware) test;
-
- frameworkTest.chainSetupTask(new Runnable()
- {
- public void run()
- {
- // Ensure that the in-vm broker is created.
- try
- {
- TransportConnection.createVMBroker(1);
- }
- catch (AMQVMBrokerCreationException e)
- {
- throw new RuntimeException("In-VM broker creation failed: " + e.getMessage(), e);
- }
- }
- });
-
- frameworkTest.chainTearDownTask(new Runnable()
- {
- public void run()
- {
- // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
- TransportConnection.killVMBroker(1);
- ApplicationRegistry.remove(1);
- }
- });
-
- // Check if the test is aware whether or not it can control the broker life cycle, and if so provide
- // additional instrumentation for it to control the in-vm broker through.
- if (test instanceof BrokerLifecycleAware)
- {
- BrokerLifecycleAware inVMTest = (BrokerLifecycleAware) test;
- inVMTest.setInVmBrokers();
- inVMTest.setLiveBroker(1);
- inVMTest.setFailureMechanism(new CauseFailureInVM(inVMTest));
- }
- }
- }
-
- // Run the test.
- test.run(testResult);
- }
-
- /**
- * Prints the name of the test for debugging purposes.
- *
- * @return The name of the test.
- */
- public String toString()
- {
- return "InVMBrokerDecorator: [test = " + test + "]";
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.framework.qpid;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.test.framework.BrokerLifecycleAware;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+
+import org.apache.qpid.junit.extensions.SetupTaskAware;
+import org.apache.qpid.junit.extensions.WrappedSuiteTestDecorator;
+
+/**
+ * InVMBrokerDecorator is a test decorator, that is activated when running tests against an in-vm broker only. Its
+ * purpose is to automatically create, and close and delete an in-vm broker, during the set-up and tear-down of
+ * each test case. This decorator may only be used in conjunction with tests that extend {@link FrameworkBaseCase}.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Create/Destroy an in-vm broker on every test run.
+ * </table>
+ *
+ * @todo May need to add a more fine grained injection point for the in-vm broker management, as this acts at the
+ * suite level, rather than the individual test level.
+ *
+ * @todo Management of in-vm brokers for failure testing. Failure test setups may need to set their connection url to
+ * use multiple broker (vm://:1;vm://:2), with fail-over between them. There is round-robin fail-over, but also
+ * retry? A test case using an in-vm broker needs to record which one it is using, so that it can be
+ * killed/restarted.
+ */
+public class InVMBrokerDecorator extends WrappedSuiteTestDecorator
+{
+ /** The test suite to run. */
+ private Test test;
+
+ /**
+ * Creates a wrapped test suite decorator from another one.
+ *
+ * @param test The test suite.
+ */
+ public InVMBrokerDecorator(WrappedSuiteTestDecorator test)
+ {
+ super(test);
+ this.test = test;
+ }
+
+ /**
+ * Runs the tests with in-vm broker creation and clean-up added to the tests task stack.
+ *
+ * @param testResult The the results object to monitor the test results with.
+ */
+ public void run(TestResult testResult)
+ {
+ for (Test test : getAllUnderlyingTests())
+ {
+ // Check that the test to have an in-vm broker setup/teardown task added to it, is actually a framework
+ // test that can handle setup tasks.
+ if ((test instanceof SetupTaskAware))
+ {
+ SetupTaskAware frameworkTest = (SetupTaskAware) test;
+
+ frameworkTest.chainSetupTask(new Runnable()
+ {
+ public void run()
+ {
+ // Ensure that the in-vm broker is created.
+ try
+ {
+ TransportConnection.createVMBroker(1);
+ }
+ catch (AMQVMBrokerCreationException e)
+ {
+ throw new RuntimeException("In-VM broker creation failed: " + e.getMessage(), e);
+ }
+ }
+ });
+
+ frameworkTest.chainTearDownTask(new Runnable()
+ {
+ public void run()
+ {
+ // Ensure that the in-vm broker is cleaned up so that the next test starts afresh.
+ TransportConnection.killVMBroker(1);
+ ApplicationRegistry.remove(1);
+ }
+ });
+
+ // Check if the test is aware whether or not it can control the broker life cycle, and if so provide
+ // additional instrumentation for it to control the in-vm broker through.
+ if (test instanceof BrokerLifecycleAware)
+ {
+ BrokerLifecycleAware inVMTest = (BrokerLifecycleAware) test;
+ inVMTest.setInVmBrokers();
+ inVMTest.setLiveBroker(1);
+ inVMTest.setFailureMechanism(new CauseFailureInVM(inVMTest));
+ }
+ }
+ }
+
+ // Run the test.
+ test.run(testResult);
+ }
+
+ /**
+ * Prints the name of the test for debugging purposes.
+ *
+ * @return The name of the test.
+ */
+ public String toString()
+ {
+ return "InVMBrokerDecorator: [test = " + test + "]";
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/FailoverTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/FailoverTest.java
index e7d874ffa9..5f41a07949 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/FailoverTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/FailoverTest.java
@@ -1,119 +1,119 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.testcases;
-
-import org.apache.qpid.test.framework.*;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import javax.jms.JMSException;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-
-/**
- * FailoverTest provides testing of fail-over over a local-circuit implementation. The circuit being tested may be
- * against an in-vm broker or against an external broker, with the failure mechanism abstracted out of the test case.
- * Automatic failures can be simulated against an in-vm broker. Currently the test must interact with the user to
- * simulate failures on an external broker.
- *
- * Things to test:
- * In tx, failure duing tx causes tx to error on subsequent sends/receives or commits/rollbacks.
- * Outside of tx, reconnection allows msg flow to continue but there may be loss.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- *
- * @todo This test is designed to be run over a local circuit only. For in-vm using automatic failures, for external
- * brokers by prompting the user (or maybe using a script). Enforce the local-circuit only nature of the tests as
- * well as thinking about how other local-circuit tests might be implemented. For example, could add a method
- * to the framework base case for local only tests to call, that allows them access to the local-circuit
- * implementation and so on.
- *
- * @todo More. Need to really expand the set of fail-over tests.
- */
-public class FailoverTest extends FrameworkBaseCase
-{
- /* Used for debugging purposes. */
- // private static final Logger log = Logger.getLogger(FailoverTest.class);
-
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public FailoverTest(String name)
- {
- super(name);
- }
-
- /**
- * Checks that all messages sent within a transaction are receieved despite a fail-over occuring outside of
- * the transaction.
- *
- * @throws JMSException Allowed to fall through and fail test.
- */
- public void testTxP2PFailover() throws JMSException
- {
- // Set up the test properties to match the test cases requirements.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // MessagingTestConfigProperties props = this.getTestParameters();
-
- // Create the test circuit from the test configuration parameters.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Create an assertion that all messages are received.
- Assertion allMessagesReceived = testCircuit.getReceiver().allMessagesReceivedAssertion(testProps);
-
- // This test case assumes it is using a local circuit.
- LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit;
-
- Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession();
- MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer();
- // MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer();
-
- // Send some test messages.
- for (int i = 0; i < 100; i++)
- {
- producer.send(TestUtils.createTestMessageOfSize(producerSession, 10));
- producerSession.commit();
-
- // Cause a failover.
- if (i == 50)
- {
- failureMechanism.causeFailure();
- }
-
- // Wait for the reconnection to complete.
- }
-
- // Check that trying to send within the original transaction fails.
-
- // Check that all messages sent were received.
- assertTrue("All messages sent were not received back again.", allMessagesReceived.apply());
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.*;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+/**
+ * FailoverTest provides testing of fail-over over a local-circuit implementation. The circuit being tested may be
+ * against an in-vm broker or against an external broker, with the failure mechanism abstracted out of the test case.
+ * Automatic failures can be simulated against an in-vm broker. Currently the test must interact with the user to
+ * simulate failures on an external broker.
+ *
+ * Things to test:
+ * In tx, failure duing tx causes tx to error on subsequent sends/receives or commits/rollbacks.
+ * Outside of tx, reconnection allows msg flow to continue but there may be loss.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo This test is designed to be run over a local circuit only. For in-vm using automatic failures, for external
+ * brokers by prompting the user (or maybe using a script). Enforce the local-circuit only nature of the tests as
+ * well as thinking about how other local-circuit tests might be implemented. For example, could add a method
+ * to the framework base case for local only tests to call, that allows them access to the local-circuit
+ * implementation and so on.
+ *
+ * @todo More. Need to really expand the set of fail-over tests.
+ */
+public class FailoverTest extends FrameworkBaseCase
+{
+ /* Used for debugging purposes. */
+ // private static final Logger log = Logger.getLogger(FailoverTest.class);
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public FailoverTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Checks that all messages sent within a transaction are receieved despite a fail-over occuring outside of
+ * the transaction.
+ *
+ * @throws JMSException Allowed to fall through and fail test.
+ */
+ public void testTxP2PFailover() throws JMSException
+ {
+ // Set up the test properties to match the test cases requirements.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // MessagingTestConfigProperties props = this.getTestParameters();
+
+ // Create the test circuit from the test configuration parameters.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Create an assertion that all messages are received.
+ Assertion allMessagesReceived = testCircuit.getReceiver().allMessagesReceivedAssertion(testProps);
+
+ // This test case assumes it is using a local circuit.
+ LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit;
+
+ Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession();
+ MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer();
+ // MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer();
+
+ // Send some test messages.
+ for (int i = 0; i < 100; i++)
+ {
+ producer.send(TestUtils.createTestMessageOfSize(producerSession, 10));
+ producerSession.commit();
+
+ // Cause a failover.
+ if (i == 50)
+ {
+ failureMechanism.causeFailure();
+ }
+
+ // Wait for the reconnection to complete.
+ }
+
+ // Check that trying to send within the original transaction fails.
+
+ // Check that all messages sent were received.
+ assertTrue("All messages sent were not received back again.", allMessagesReceived.apply());
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java
index 845c3ed9c8..767871e25a 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/ImmediateMessageTest.java
@@ -1,303 +1,303 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.testcases;
-
-import org.apache.qpid.test.framework.AMQPPublisher;
-import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import org.apache.qpid.test.framework.MessagingTestConfigProperties;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-/**
- * ImmediateMessageTest tests for the desired behaviour of immediate messages. Immediate messages are a non-JMS
- * feature. A message may be marked with an immediate delivery flag, which means that a consumer must be connected
- * to receive the message, through a valid route, when it is sent, or when its transaction is committed in the case
- * of transactional messaging. If this is not the case, the broker should return the message with a NO_CONSUMERS code.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check that an immediate message is sent succesfully not using transactions when a consumer is connected.
- * <tr><td> Check that an immediate message is committed succesfully in a transaction when a consumer is connected.
- * <tr><td> Check that an immediate message results in no consumers code, not using transactions, when a consumer is
- * disconnected.
- * <tr><td> Check that an immediate message results in no consumers code, in a transaction, when a consumer is
- * disconnected.
- * <tr><td> Check that an immediate message results in no route code, not using transactions, when no outgoing route is
- * connected.
- * <tr><td> Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is
- * connected.
- * <tr><td> Check that an immediate message is sent succesfully not using transactions when a consumer is connected.
- * <tr><td> Check that an immediate message is committed succesfully in a transaction when a consumer is connected.
- * <tr><td> Check that an immediate message results in no consumers code, not using transactions, when a consumer is
- * disconnected.
- * <tr><td> Check that an immediate message results in no consumers code, in a transaction, when a consumer is
- * disconnected.
- * <tr><td> Check that an immediate message results in no route code, not using transactions, when no outgoing route is
- * connected.
- * <tr><td> Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is
- * connected.
- * </table>
- *
- * @todo All of these test cases will be generated by a test generator that thoroughly tests all combinations of test
- * circuits.
- */
-public class ImmediateMessageTest extends FrameworkBaseCase
-{
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public ImmediateMessageTest(String name)
- {
- super(name);
- }
-
- /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
- public void test_QPID_517_ImmediateOkNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
- }
-
- /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
- public void test_QPID_517_ImmediateOkTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Send one message with no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
- public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
- public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
- public void test_QPID_517_ImmediateFailsNoRouteNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
- public void test_QPID_517_ImmediateFailsNoRouteTxP2P()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
- public void test_QPID_517_ImmediateOkNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Send one message with no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
- public void test_QPID_517_ImmediateOkTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Send one message with no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
- public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Use durable subscriptions, so that the route remains open with no subscribers.
- testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
- public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Use durable subscriptions, so that the route remains open with no subscribers.
- testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message and get a linked no consumers exception.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
- public void test_QPID_517_ImmediateFailsNoRouteNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
- public void test_QPID_517_ImmediateFailsNoRouteTxPubSub()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- protected void setUp() throws Exception
- {
- super.setUp();
-
- testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
-
- /** All these tests should have the immediate flag on. */
- testProps.setProperty(IMMEDIATE_PROPNAME, true);
- testProps.setProperty(MANDATORY_PROPNAME, false);
-
- /** Bind the receivers consumer by default. */
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.AMQPPublisher;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+/**
+ * ImmediateMessageTest tests for the desired behaviour of immediate messages. Immediate messages are a non-JMS
+ * feature. A message may be marked with an immediate delivery flag, which means that a consumer must be connected
+ * to receive the message, through a valid route, when it is sent, or when its transaction is committed in the case
+ * of transactional messaging. If this is not the case, the broker should return the message with a NO_CONSUMERS code.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check that an immediate message is sent succesfully not using transactions when a consumer is connected.
+ * <tr><td> Check that an immediate message is committed succesfully in a transaction when a consumer is connected.
+ * <tr><td> Check that an immediate message results in no consumers code, not using transactions, when a consumer is
+ * disconnected.
+ * <tr><td> Check that an immediate message results in no consumers code, in a transaction, when a consumer is
+ * disconnected.
+ * <tr><td> Check that an immediate message results in no route code, not using transactions, when no outgoing route is
+ * connected.
+ * <tr><td> Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is
+ * connected.
+ * <tr><td> Check that an immediate message is sent succesfully not using transactions when a consumer is connected.
+ * <tr><td> Check that an immediate message is committed succesfully in a transaction when a consumer is connected.
+ * <tr><td> Check that an immediate message results in no consumers code, not using transactions, when a consumer is
+ * disconnected.
+ * <tr><td> Check that an immediate message results in no consumers code, in a transaction, when a consumer is
+ * disconnected.
+ * <tr><td> Check that an immediate message results in no route code, not using transactions, when no outgoing route is
+ * connected.
+ * <tr><td> Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is
+ * connected.
+ * </table>
+ *
+ * @todo All of these test cases will be generated by a test generator that thoroughly tests all combinations of test
+ * circuits.
+ */
+public class ImmediateMessageTest extends FrameworkBaseCase
+{
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public ImmediateMessageTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
+ public void test_QPID_517_ImmediateOkNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
+ public void test_QPID_517_ImmediateOkTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Send one message with no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
+ public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message and get a linked no consumers exception.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
+ public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxP2P()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message and get a linked no consumers exception.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
+ public void test_QPID_517_ImmediateFailsNoRouteNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
+ public void test_QPID_517_ImmediateFailsNoRouteTxP2P()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an immediate message is sent succesfully not using transactions when a consumer is connected. */
+ public void test_QPID_517_ImmediateOkNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Send one message with no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an immediate message is committed succesfully in a transaction when a consumer is connected. */
+ public void test_QPID_517_ImmediateOkTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Send one message with no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no consumers code, not using transactions, when a consumer is disconnected. */
+ public void test_QPID_517_ImmediateFailsConsumerDisconnectedNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Use durable subscriptions, so that the route remains open with no subscribers.
+ testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message and get a linked no consumers exception.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no consumers code, in a transaction, when a consumer is disconnected. */
+ public void test_QPID_517_ImmediateFailsConsumerDisconnectedTxPubSub()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Use durable subscriptions, so that the route remains open with no subscribers.
+ testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message and get a linked no consumers exception.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noConsumersAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no route code, not using transactions, when no outgoing route is connected. */
+ public void test_QPID_517_ImmediateFailsNoRouteNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an immediate message results in no route code, upon transaction commit, when no outgoing route is connected. */
+ public void test_QPID_517_ImmediateFailsNoRouteTxPubSub()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /** All these tests should have the immediate flag on. */
+ testProps.setProperty(IMMEDIATE_PROPNAME, true);
+ testProps.setProperty(MANDATORY_PROPNAME, false);
+
+ /** Bind the receivers consumer by default. */
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java
index 066b4e24ba..d46a866b93 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/MandatoryMessageTest.java
@@ -1,321 +1,321 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.testcases;
-
-import org.apache.qpid.test.framework.AMQPPublisher;
-import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import org.apache.qpid.test.framework.MessagingTestConfigProperties;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-/**
- * MandatoryMessageTest tests for the desired behaviour of mandatory messages. Mandatory messages are a non-JMS
- * feature. A message may be marked with a mandatory delivery flag, which means that a valid route for the message
- * must exist, when it is sent, or when its transaction is committed in the case of transactional messaging. If this
- * is not the case, the broker should return the message with a NO_CONSUMERS code.
- *
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check that an mandatory message is sent succesfully not using transactions when a consumer is connected.
- * <tr><td> Check that an mandatory message is committed succesfully in a transaction when a consumer is connected.
- * <tr><td> Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected
- * but the route exists.
- * <tr><td> Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
- * the route exists.
- * <tr><td> Check that an mandatory message results in no route code, not using transactions, when no consumer is
- * connected.
- * <tr><td> Check that an mandatory message results in no route code, upon transaction commit, when a consumer is
- * connected.
- * <tr><td> Check that an mandatory message is sent succesfully not using transactions when a consumer is connected.
- * <tr><td> Check that an mandatory message is committed succesfully in a transaction when a consumer is connected.
- * <tr><td> Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected
- * but the route exists.
- * <tr><td> Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
- * the route exists.
- * <tr><td> Check that an mandatory message results in no route code, not using transactions, when no consumer is
- * connected.
- * <tr><td> Check that an mandatory message results in no route code, upon transaction commit, when a consumer is
- * connected.
- * </table>
- *
- * @todo All of these test cases will be generated by a test generator that thoroughly tests all combinations of test
- * circuits.
- */
-public class MandatoryMessageTest extends FrameworkBaseCase
-{
- /** Used to read the tests configurable properties through. */
- ParsedProperties testProps;
-
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public MandatoryMessageTest(String name)
- {
- super(name);
- }
-
- /** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
- public void test_QPID_508_MandatoryOkNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
- public void test_QPID_508_MandatoryOkTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /**
- * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but
- * the route exists.
- */
- public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /**
- * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
- * the route exists.
- */
- public void test_QPID_517_MandatoryOkConsumerDisconnectedTxP2P()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
- public void test_QPID_508_MandatoryFailsNoRouteNoTxP2P()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
- public void test_QPID_508_MandatoryFailsNoRouteTxP2P()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
- public void test_QPID_508_MandatoryOkNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
- public void test_QPID_508_MandatoryOkTxPubSub()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /**
- * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but
- * the route exists.
- */
- public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Use durable subscriptions, so that the route remains open with no subscribers.
- testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /**
- * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
- * the route exists.
- */
- public void test_QPID_517_MandatoryOkConsumerDisconnectedTxPubSub()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Use durable subscriptions, so that the route remains open with no subscribers.
- testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
-
- // Disconnect the consumer.
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
-
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // Send one message with no errors.
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
- }
-
- /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
- public void test_QPID_508_MandatoryFailsNoRouteNoTxPubSub()
- {
- // Ensure transactional sessions are off.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
- public void test_QPID_508_MandatoryFailsNoRouteTxPubSub()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(PUBSUB_PROPNAME, true);
-
- // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
- // collect its messages).
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
-
- // Send one message and get a linked no route exception.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
- }
-
- protected void setUp() throws Exception
- {
- super.setUp();
-
- testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
-
- /** All these tests should have the mandatory flag on. */
- testProps.setProperty(IMMEDIATE_PROPNAME, false);
- testProps.setProperty(MANDATORY_PROPNAME, true);
-
- /** Bind the receivers consumer by default. */
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.AMQPPublisher;
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+/**
+ * MandatoryMessageTest tests for the desired behaviour of mandatory messages. Mandatory messages are a non-JMS
+ * feature. A message may be marked with a mandatory delivery flag, which means that a valid route for the message
+ * must exist, when it is sent, or when its transaction is committed in the case of transactional messaging. If this
+ * is not the case, the broker should return the message with a NO_CONSUMERS code.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check that an mandatory message is sent succesfully not using transactions when a consumer is connected.
+ * <tr><td> Check that an mandatory message is committed succesfully in a transaction when a consumer is connected.
+ * <tr><td> Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected
+ * but the route exists.
+ * <tr><td> Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
+ * the route exists.
+ * <tr><td> Check that an mandatory message results in no route code, not using transactions, when no consumer is
+ * connected.
+ * <tr><td> Check that an mandatory message results in no route code, upon transaction commit, when a consumer is
+ * connected.
+ * <tr><td> Check that an mandatory message is sent succesfully not using transactions when a consumer is connected.
+ * <tr><td> Check that an mandatory message is committed succesfully in a transaction when a consumer is connected.
+ * <tr><td> Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected
+ * but the route exists.
+ * <tr><td> Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
+ * the route exists.
+ * <tr><td> Check that an mandatory message results in no route code, not using transactions, when no consumer is
+ * connected.
+ * <tr><td> Check that an mandatory message results in no route code, upon transaction commit, when a consumer is
+ * connected.
+ * </table>
+ *
+ * @todo All of these test cases will be generated by a test generator that thoroughly tests all combinations of test
+ * circuits.
+ */
+public class MandatoryMessageTest extends FrameworkBaseCase
+{
+ /** Used to read the tests configurable properties through. */
+ ParsedProperties testProps;
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public MandatoryMessageTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
+ public void test_QPID_508_MandatoryOkNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
+ public void test_QPID_508_MandatoryOkTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /**
+ * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but
+ * the route exists.
+ */
+ public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message with no errors.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /**
+ * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
+ * the route exists.
+ */
+ public void test_QPID_517_MandatoryOkConsumerDisconnectedTxP2P()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message with no errors.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
+ public void test_QPID_508_MandatoryFailsNoRouteNoTxP2P()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
+ public void test_QPID_508_MandatoryFailsNoRouteTxP2P()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message is sent succesfully not using transactions when a consumer is connected. */
+ public void test_QPID_508_MandatoryOkNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message is committed succesfully in a transaction when a consumer is connected. */
+ public void test_QPID_508_MandatoryOkTxPubSub()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /**
+ * Check that a mandatory message is sent succesfully, not using transactions, when a consumer is disconnected but
+ * the route exists.
+ */
+ public void test_QPID_517_MandatoryOkConsumerDisconnectedNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Use durable subscriptions, so that the route remains open with no subscribers.
+ testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message with no errors.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /**
+ * Check that a mandatory message is sent succesfully, in a transaction, when a consumer is disconnected but
+ * the route exists.
+ */
+ public void test_QPID_517_MandatoryOkConsumerDisconnectedTxPubSub()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Use durable subscriptions, so that the route remains open with no subscribers.
+ testProps.setProperty(DURABLE_SUBSCRIPTION_PROPNAME, true);
+
+ // Disconnect the consumer.
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, false);
+
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // Send one message with no errors.
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noExceptionsAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message results in no route code, not using transactions, when no consumer is connected. */
+ public void test_QPID_508_MandatoryFailsNoRouteNoTxPubSub()
+ {
+ // Ensure transactional sessions are off.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ /** Check that an mandatory message results in no route code, upon transaction commit, when a consumer is connected. */
+ public void test_QPID_508_MandatoryFailsNoRouteTxPubSub()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(PUBSUB_PROPNAME, true);
+
+ // Set up the messaging topology so that only the publishers producer is bound (do not set up the receivers to
+ // collect its messages).
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, false);
+
+ // Send one message and get a linked no route exception.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(((AMQPPublisher) testCircuit.getPublisher()).noRouteAssertion(testProps))));
+ }
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /** All these tests should have the mandatory flag on. */
+ testProps.setProperty(IMMEDIATE_PROPNAME, false);
+ testProps.setProperty(MANDATORY_PROPNAME, true);
+
+ /** Bind the receivers consumer by default. */
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java
index f39d22bc67..c1a484b2aa 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/RollbackTest.java
@@ -1,132 +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.test.testcases;
-
-import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import org.apache.qpid.test.framework.MessagingTestConfigProperties;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import org.apache.qpid.junit.extensions.util.ParsedProperties;
-import org.apache.qpid.junit.extensions.util.TestContextProperties;
-
-/**
- * RollbackTest tests the rollback ability of transactional messaging.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Check messages sent but rolled back are never received.
- * <tr><td> Check messages received but rolled back are redelivered on subsequent receives.
- * <tr><td> Attempting to rollback outside of a transaction results in an IllegalStateException.
- * </table>
- */
-public class RollbackTest extends FrameworkBaseCase
-{
- /** Used to read the tests configurable properties through. */
- ParsedProperties testProps;
-
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public RollbackTest(String name)
- {
- super(name);
- }
-
- /** Check messages sent but rolled back are never received. */
- public void testRolledbackMessageNotDelivered()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
- testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
- testCircuit.getReceiver().noMessagesReceivedAssertion(testProps))));
- }
-
- /** Check messages received but rolled back are redelivered on subsequent receives. */
- public void testRolledbackMessagesSubsequentlyReceived()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, true);
- testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1,
- assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
- testCircuit.getReceiver().allMessagesReceivedAssertion(testProps))));
- }
-
- /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
- public void testRollbackUnavailableOutsideTransactionPublisher()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
- testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().channelClosedAssertion(testProps))));
- }
-
- /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
- public void testRollbackUnavailableOutsideTransactionReceiver()
- {
- // Ensure transactional sessions are on.
- testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, false);
- testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
-
- // Run the default test sequence over the test circuit checking for no errors.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getReceiver().channelClosedAssertion(testProps))));
- }
-
- /**
- * Sets up all tests to have an active outward route and consumer by default.
- *
- * @throws Exception Any exceptions are allowed to fall through and fail the test.
- */
- protected void setUp() throws Exception
- {
- super.setUp();
-
- testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
-
- /** Bind the receivers consumer by default. */
- testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
- testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import org.apache.qpid.test.framework.MessagingTestConfigProperties;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.*;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import org.apache.qpid.junit.extensions.util.ParsedProperties;
+import org.apache.qpid.junit.extensions.util.TestContextProperties;
+
+/**
+ * RollbackTest tests the rollback ability of transactional messaging.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Check messages sent but rolled back are never received.
+ * <tr><td> Check messages received but rolled back are redelivered on subsequent receives.
+ * <tr><td> Attempting to rollback outside of a transaction results in an IllegalStateException.
+ * </table>
+ */
+public class RollbackTest extends FrameworkBaseCase
+{
+ /** Used to read the tests configurable properties through. */
+ ParsedProperties testProps;
+
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public RollbackTest(String name)
+ {
+ super(name);
+ }
+
+ /** Check messages sent but rolled back are never received. */
+ public void testRolledbackMessageNotDelivered()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, true);
+ testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
+ testCircuit.getReceiver().noMessagesReceivedAssertion(testProps))));
+ }
+
+ /** Check messages received but rolled back are redelivered on subsequent receives. */
+ public void testRolledbackMessagesSubsequentlyReceived()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, true);
+ testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1,
+ assertionList(testCircuit.getPublisher().noExceptionsAssertion(testProps),
+ testCircuit.getReceiver().allMessagesReceivedAssertion(testProps))));
+ }
+
+ /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
+ public void testRollbackUnavailableOutsideTransactionPublisher()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_PUBLISHER_PROPNAME, false);
+ testProps.setProperty(ROLLBACK_PUBLISHER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getPublisher().channelClosedAssertion(testProps))));
+ }
+
+ /** Attempting to rollback outside of a transaction results in an IllegalStateException. */
+ public void testRollbackUnavailableOutsideTransactionReceiver()
+ {
+ // Ensure transactional sessions are on.
+ testProps.setProperty(TRANSACTED_RECEIVER_PROPNAME, false);
+ testProps.setProperty(ROLLBACK_RECEIVER_PROPNAME, true);
+
+ // Run the default test sequence over the test circuit checking for no errors.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ assertNoFailures(testCircuit.test(1, assertionList(testCircuit.getReceiver().channelClosedAssertion(testProps))));
+ }
+
+ /**
+ * Sets up all tests to have an active outward route and consumer by default.
+ *
+ * @throws Exception Any exceptions are allowed to fall through and fail the test.
+ */
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ testProps = TestContextProperties.getInstance(MessagingTestConfigProperties.defaults);
+
+ /** Bind the receivers consumer by default. */
+ testProps.setProperty(RECEIVER_CONSUMER_BIND_PROPNAME, true);
+ testProps.setProperty(RECEIVER_CONSUMER_ACTIVE_PROPNAME, true);
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java
index f752ccba00..9004cb72df 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/testcases/TTLTest.java
@@ -1,151 +1,151 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.testcases;
-
-import org.apache.qpid.test.framework.Circuit;
-import org.apache.qpid.test.framework.FrameworkBaseCase;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.ACK_MODE_PROPNAME;
-import static org.apache.qpid.test.framework.MessagingTestConfigProperties.PUBSUB_PROPNAME;
-import org.apache.qpid.test.framework.TestUtils;
-import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
-import org.apache.qpid.test.framework.sequencers.CircuitFactory;
-
-import javax.jms.*;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-
-/**
- * TTLTest checks that time-to-live is applied to messages. The test sends messages with a variety of TTL stamps on them
- * then after a pause attempts to receive those messages. Only messages with a large enough TTL to have survived the pause
- * should be receiveable. This test case also applies an additional assertion against the broker, that the message store
- * is empty at the end of the test.
- *
- * <p/>This test is designed to run over local circuits only, as it must control a timed pause between sending and receiving
- * messages to that TTL can be applied to purge some of the messages.
- *
- * <p/><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td>
- * </table>
- *
- * @todo Use an interface or other method to mark this test as local only.
- *
- * @todo Implement the message store assertion for in-vm broker. Could also be done for external broker, for example
- * by using diagnostic exchange.
- *
- * @todo Implement and add a queue depth assertion too. This might already be in another test to copy from.
- *
- * @todo Create variations on test theme, for different ack mode and tx and message sizes etc.
- *
- * @todo Add an allowable margin of error to the test, as ttl may not be precise.
- */
-public class TTLTest extends FrameworkBaseCase
-{
- /**
- * Creates a new test case with the specified name.
- *
- * @param name The test case name.
- */
- public TTLTest(String name)
- {
- super(name);
- }
-
- /**
- * Checks that all messages sent with a TTL shorter than a pause between sending them and attempting to receive them
- * will fail to arrive. Once all messages have been purged by TTL or received, check that they no longer exist on
- * the broker.
- *
- * @throws javax.jms.JMSException Allowed to fall through and fail test.
- */
- public void testTTLP2P() throws JMSException
- {
- String errorMessages = "";
- Random r = new Random();
-
- // Used to accumulate correctly received messages in.
- List<Message> receivedMessages = new LinkedList<Message>();
-
- // Set up the test properties to match the test case requirements.
- testProps.setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE);
- testProps.setProperty(PUBSUB_PROPNAME, false);
-
- // Create the test circuit from the test configuration parameters.
- CircuitFactory circuitFactory = getCircuitFactory();
- Circuit testCircuit = circuitFactory.createCircuit(testProps);
-
- // This test case assumes it is using a local circuit.
- LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit;
-
- Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession();
- MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer();
- MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer();
-
- // Send some tests messages, with random TTLs, some shorter and some longer than the pause time.
- for (int i = 0; i < 100; i++)
- {
- Message testMessage = TestUtils.createTestMessageOfSize(producerSession, 10);
-
- // Set the TTL on the message and record its value in the message headers.
- long ttl = 500 + r.nextInt(1500);
- producer.setTimeToLive(ttl);
- testMessage.setLongProperty("testTTL", ttl);
-
- producer.send(testMessage);
- // producerSession.commit();
- }
-
- // Inject a pause to allow some messages to be purged by TTL.
- TestUtils.pause(1000);
-
- // Attempt to receive back all of the messages, confirming by the message time stamps and TTLs that only
- // those received should have avoided being purged by the TTL.
- boolean timedOut = false;
-
- while (!timedOut)
- {
- Message testMessage = consumer.receive(1000);
-
- long ttl = testMessage.getLongProperty("testTTL");
- long timeStamp = testMessage.getJMSTimestamp();
- long now = System.currentTimeMillis();
-
- if ((timeStamp + ttl) < now)
- {
- errorMessages +=
- "Received message [sent: " + timeStamp + ", ttl: " + ttl + ", received: " + now
- + "] which should have been purged by its TTL.\n";
- }
- /*else
- {
- receivedMessages.add(testMessage);
- }*/
- }
-
- // Check that the queue and message store on the broker are empty.
- // assertTrue("Message store is not empty.", messageStoreEmpty.apply());
- // assertTrue("Queue is not empty.", queueEmpty.apply());
-
- assertTrue(errorMessages, "".equals(errorMessages));
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.test.testcases;
+
+import org.apache.qpid.test.framework.Circuit;
+import org.apache.qpid.test.framework.FrameworkBaseCase;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.ACK_MODE_PROPNAME;
+import static org.apache.qpid.test.framework.MessagingTestConfigProperties.PUBSUB_PROPNAME;
+import org.apache.qpid.test.framework.TestUtils;
+import org.apache.qpid.test.framework.localcircuit.LocalCircuitImpl;
+import org.apache.qpid.test.framework.sequencers.CircuitFactory;
+
+import javax.jms.*;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * TTLTest checks that time-to-live is applied to messages. The test sends messages with a variety of TTL stamps on them
+ * then after a pause attempts to receive those messages. Only messages with a large enough TTL to have survived the pause
+ * should be receiveable. This test case also applies an additional assertion against the broker, that the message store
+ * is empty at the end of the test.
+ *
+ * <p/>This test is designed to run over local circuits only, as it must control a timed pause between sending and receiving
+ * messages to that TTL can be applied to purge some of the messages.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td>
+ * </table>
+ *
+ * @todo Use an interface or other method to mark this test as local only.
+ *
+ * @todo Implement the message store assertion for in-vm broker. Could also be done for external broker, for example
+ * by using diagnostic exchange.
+ *
+ * @todo Implement and add a queue depth assertion too. This might already be in another test to copy from.
+ *
+ * @todo Create variations on test theme, for different ack mode and tx and message sizes etc.
+ *
+ * @todo Add an allowable margin of error to the test, as ttl may not be precise.
+ */
+public class TTLTest extends FrameworkBaseCase
+{
+ /**
+ * Creates a new test case with the specified name.
+ *
+ * @param name The test case name.
+ */
+ public TTLTest(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Checks that all messages sent with a TTL shorter than a pause between sending them and attempting to receive them
+ * will fail to arrive. Once all messages have been purged by TTL or received, check that they no longer exist on
+ * the broker.
+ *
+ * @throws javax.jms.JMSException Allowed to fall through and fail test.
+ */
+ public void testTTLP2P() throws JMSException
+ {
+ String errorMessages = "";
+ Random r = new Random();
+
+ // Used to accumulate correctly received messages in.
+ List<Message> receivedMessages = new LinkedList<Message>();
+
+ // Set up the test properties to match the test case requirements.
+ testProps.setProperty(ACK_MODE_PROPNAME, Session.AUTO_ACKNOWLEDGE);
+ testProps.setProperty(PUBSUB_PROPNAME, false);
+
+ // Create the test circuit from the test configuration parameters.
+ CircuitFactory circuitFactory = getCircuitFactory();
+ Circuit testCircuit = circuitFactory.createCircuit(testProps);
+
+ // This test case assumes it is using a local circuit.
+ LocalCircuitImpl localCircuit = (LocalCircuitImpl) testCircuit;
+
+ Session producerSession = localCircuit.getLocalPublisherCircuitEnd().getSession();
+ MessageProducer producer = localCircuit.getLocalPublisherCircuitEnd().getProducer();
+ MessageConsumer consumer = localCircuit.getLocalReceiverCircuitEnd().getConsumer();
+
+ // Send some tests messages, with random TTLs, some shorter and some longer than the pause time.
+ for (int i = 0; i < 100; i++)
+ {
+ Message testMessage = TestUtils.createTestMessageOfSize(producerSession, 10);
+
+ // Set the TTL on the message and record its value in the message headers.
+ long ttl = 500 + r.nextInt(1500);
+ producer.setTimeToLive(ttl);
+ testMessage.setLongProperty("testTTL", ttl);
+
+ producer.send(testMessage);
+ // producerSession.commit();
+ }
+
+ // Inject a pause to allow some messages to be purged by TTL.
+ TestUtils.pause(1000);
+
+ // Attempt to receive back all of the messages, confirming by the message time stamps and TTLs that only
+ // those received should have avoided being purged by the TTL.
+ boolean timedOut = false;
+
+ while (!timedOut)
+ {
+ Message testMessage = consumer.receive(1000);
+
+ long ttl = testMessage.getLongProperty("testTTL");
+ long timeStamp = testMessage.getJMSTimestamp();
+ long now = System.currentTimeMillis();
+
+ if ((timeStamp + ttl) < now)
+ {
+ errorMessages +=
+ "Received message [sent: " + timeStamp + ", ttl: " + ttl + ", received: " + now
+ + "] which should have been purged by its TTL.\n";
+ }
+ /*else
+ {
+ receivedMessages.add(testMessage);
+ }*/
+ }
+
+ // Check that the queue and message store on the broker are empty.
+ // assertTrue("Message store is not empty.", messageStoreEmpty.apply());
+ // assertTrue("Queue is not empty.", queueEmpty.apply());
+
+ assertTrue(errorMessages, "".equals(errorMessages));
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java
index 398e3e7800..c43b65a805 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnectionHelper.java
@@ -1,296 +1,296 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-package org.apache.qpid.testutil;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.client.JMSAMQException;
-import org.apache.qpid.url.URLSyntaxException;
-
-import javax.jms.Connection;
-import javax.jms.DeliveryMode;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
-/**
- * @todo This was originally cut and paste from the client module leading to a duplicate class, then altered very
- * slightly. To avoid the duplicate class the name was altered slightly to have 'Helper' on the end in order
- * to distinguish it from the original. Delete this class and use the original instead, just upgrade it to
- * provide the new features needed.
- */
-public class QpidClientConnectionHelper implements ExceptionListener
-{
-
- private static final Logger _logger = Logger.getLogger(QpidClientConnectionHelper.class);
-
- private boolean transacted = true;
- private int ackMode = Session.CLIENT_ACKNOWLEDGE;
- private Connection connection;
-
- private String virtualHost;
- private String brokerlist;
- private int prefetch;
- protected Session session;
- protected boolean connected;
-
- public QpidClientConnectionHelper(String broker)
- {
- super();
- setVirtualHost("/test");
- setBrokerList(broker);
- setPrefetch(5000);
- }
-
- public void connect() throws JMSException
- {
- if (!connected)
- {
- /*
- * amqp://[user:pass@][clientid]/virtualhost?
- * brokerlist='[transport://]host[:port][?option='value'[&option='value']];'
- * [&failover='method[?option='value'[&option='value']]']
- * [&option='value']"
- */
- String brokerUrl = "amqp://guest:guest@" + virtualHost + "?brokerlist='" + brokerlist + "'";
- try
- {
- AMQConnectionFactory factory = new AMQConnectionFactory(new AMQConnectionURL(brokerUrl));
- _logger.info("connecting to Qpid :" + brokerUrl);
- connection = factory.createConnection();
-
- // register exception listener
- connection.setExceptionListener(this);
-
- session = ((AMQConnection) connection).createSession(transacted, ackMode, prefetch);
-
- _logger.info("starting connection");
- connection.start();
-
- connected = true;
- }
- catch (URLSyntaxException e)
- {
- throw new JMSAMQException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage(), e);
- }
- }
- }
-
- public void disconnect() throws JMSException
- {
- if (connected)
- {
- session.commit();
- session.close();
- connection.close();
- connected = false;
- _logger.info("disconnected");
- }
- }
-
- public void disconnectWithoutCommit() throws JMSException
- {
- if (connected)
- {
- session.close();
- connection.close();
- connected = false;
- _logger.info("disconnected without commit");
- }
- }
-
- public String getBrokerList()
- {
- return brokerlist;
- }
-
- public void setBrokerList(String brokerlist)
- {
- this.brokerlist = brokerlist;
- }
-
- public String getVirtualHost()
- {
- return virtualHost;
- }
-
- public void setVirtualHost(String virtualHost)
- {
- this.virtualHost = virtualHost;
- }
-
- public void setPrefetch(int prefetch)
- {
- this.prefetch = prefetch;
- }
-
- /** override as necessary */
- public void onException(JMSException exception)
- {
- _logger.info("ExceptionListener event: error " + exception.getErrorCode() + ", message: " + exception.getMessage());
- }
-
- public boolean isConnected()
- {
- return connected;
- }
-
- public Session getSession()
- {
- return session;
- }
-
- /**
- * Put a String as a text messages, repeat n times. A null payload will result in a null message.
- *
- * @param queueName The queue name to put to
- * @param payload the content of the payload
- * @param copies the number of messages to put
- *
- * @throws javax.jms.JMSException any exception that occurs
- */
- public void put(String queueName, String payload, int copies, int deliveryMode) throws JMSException
- {
- if (!connected)
- {
- connect();
- }
-
- _logger.info("putting to queue " + queueName);
- Queue queue = session.createQueue(queueName);
-
- final MessageProducer sender = session.createProducer(queue);
-
- sender.setDeliveryMode(deliveryMode);
-
- for (int i = 0; i < copies; i++)
- {
- Message m = session.createTextMessage(payload + i);
- m.setIntProperty("index", i + 1);
- sender.send(m);
- }
-
- session.commit();
- sender.close();
- _logger.info("put " + copies + " copies");
- }
-
- /**
- * GET the top message on a queue. Consumes the message. Accepts timeout value.
- *
- * @param queueName The quename to get from
- * @param readTimeout The timeout to use
- *
- * @return the content of the text message if any
- *
- * @throws javax.jms.JMSException any exception that occured
- */
- public Message getNextMessage(String queueName, long readTimeout) throws JMSException
- {
- if (!connected)
- {
- connect();
- }
-
- Queue queue = session.createQueue(queueName);
-
- final MessageConsumer consumer = session.createConsumer(queue);
-
- Message message = consumer.receive(readTimeout);
- session.commit();
- consumer.close();
-
- Message result;
-
- // all messages we consume should be TextMessages
- if (message instanceof TextMessage)
- {
- result = ((TextMessage) message);
- }
- else if (null == message)
- {
- result = null;
- }
- else
- {
- _logger.info("warning: received non-text message");
- result = message;
- }
-
- return result;
- }
-
- /**
- * GET the top message on a queue. Consumes the message.
- *
- * @param queueName The Queuename to get from
- *
- * @return The string content of the text message, if any received
- *
- * @throws javax.jms.JMSException any exception that occurs
- */
- public Message getNextMessage(String queueName) throws JMSException
- {
- return getNextMessage(queueName, 0);
- }
-
- /**
- * Completely clears a queue. For readTimeout behaviour see Javadocs for javax.jms.MessageConsumer.
- *
- * @param queueName The Queue name to consume from
- * @param readTimeout The timeout for each consume
- *
- * @throws javax.jms.JMSException Any exception that occurs during the consume
- * @throws InterruptedException If the consume thread was interrupted during a consume.
- */
- public void consume(String queueName, int readTimeout) throws JMSException, InterruptedException
- {
- if (!connected)
- {
- connect();
- }
-
- _logger.info("consuming queue " + queueName);
- Queue queue = session.createQueue(queueName);
-
- final MessageConsumer consumer = session.createConsumer(queue);
- int messagesReceived = 0;
-
- _logger.info("consuming...");
- while ((consumer.receive(readTimeout)) != null)
- {
- messagesReceived++;
- }
-
- session.commit();
- consumer.close();
- _logger.info("consumed: " + messagesReceived);
- }
-}
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.testutil;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.JMSAMQException;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+/**
+ * @todo This was originally cut and paste from the client module leading to a duplicate class, then altered very
+ * slightly. To avoid the duplicate class the name was altered slightly to have 'Helper' on the end in order
+ * to distinguish it from the original. Delete this class and use the original instead, just upgrade it to
+ * provide the new features needed.
+ */
+public class QpidClientConnectionHelper implements ExceptionListener
+{
+
+ private static final Logger _logger = Logger.getLogger(QpidClientConnectionHelper.class);
+
+ private boolean transacted = true;
+ private int ackMode = Session.CLIENT_ACKNOWLEDGE;
+ private Connection connection;
+
+ private String virtualHost;
+ private String brokerlist;
+ private int prefetch;
+ protected Session session;
+ protected boolean connected;
+
+ public QpidClientConnectionHelper(String broker)
+ {
+ super();
+ setVirtualHost("/test");
+ setBrokerList(broker);
+ setPrefetch(5000);
+ }
+
+ public void connect() throws JMSException
+ {
+ if (!connected)
+ {
+ /*
+ * amqp://[user:pass@][clientid]/virtualhost?
+ * brokerlist='[transport://]host[:port][?option='value'[&option='value']];'
+ * [&failover='method[?option='value'[&option='value']]']
+ * [&option='value']"
+ */
+ String brokerUrl = "amqp://guest:guest@" + virtualHost + "?brokerlist='" + brokerlist + "'";
+ try
+ {
+ AMQConnectionFactory factory = new AMQConnectionFactory(new AMQConnectionURL(brokerUrl));
+ _logger.info("connecting to Qpid :" + brokerUrl);
+ connection = factory.createConnection();
+
+ // register exception listener
+ connection.setExceptionListener(this);
+
+ session = ((AMQConnection) connection).createSession(transacted, ackMode, prefetch);
+
+ _logger.info("starting connection");
+ connection.start();
+
+ connected = true;
+ }
+ catch (URLSyntaxException e)
+ {
+ throw new JMSAMQException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ public void disconnect() throws JMSException
+ {
+ if (connected)
+ {
+ session.commit();
+ session.close();
+ connection.close();
+ connected = false;
+ _logger.info("disconnected");
+ }
+ }
+
+ public void disconnectWithoutCommit() throws JMSException
+ {
+ if (connected)
+ {
+ session.close();
+ connection.close();
+ connected = false;
+ _logger.info("disconnected without commit");
+ }
+ }
+
+ public String getBrokerList()
+ {
+ return brokerlist;
+ }
+
+ public void setBrokerList(String brokerlist)
+ {
+ this.brokerlist = brokerlist;
+ }
+
+ public String getVirtualHost()
+ {
+ return virtualHost;
+ }
+
+ public void setVirtualHost(String virtualHost)
+ {
+ this.virtualHost = virtualHost;
+ }
+
+ public void setPrefetch(int prefetch)
+ {
+ this.prefetch = prefetch;
+ }
+
+ /** override as necessary */
+ public void onException(JMSException exception)
+ {
+ _logger.info("ExceptionListener event: error " + exception.getErrorCode() + ", message: " + exception.getMessage());
+ }
+
+ public boolean isConnected()
+ {
+ return connected;
+ }
+
+ public Session getSession()
+ {
+ return session;
+ }
+
+ /**
+ * Put a String as a text messages, repeat n times. A null payload will result in a null message.
+ *
+ * @param queueName The queue name to put to
+ * @param payload the content of the payload
+ * @param copies the number of messages to put
+ *
+ * @throws javax.jms.JMSException any exception that occurs
+ */
+ public void put(String queueName, String payload, int copies, int deliveryMode) throws JMSException
+ {
+ if (!connected)
+ {
+ connect();
+ }
+
+ _logger.info("putting to queue " + queueName);
+ Queue queue = session.createQueue(queueName);
+
+ final MessageProducer sender = session.createProducer(queue);
+
+ sender.setDeliveryMode(deliveryMode);
+
+ for (int i = 0; i < copies; i++)
+ {
+ Message m = session.createTextMessage(payload + i);
+ m.setIntProperty("index", i + 1);
+ sender.send(m);
+ }
+
+ session.commit();
+ sender.close();
+ _logger.info("put " + copies + " copies");
+ }
+
+ /**
+ * GET the top message on a queue. Consumes the message. Accepts timeout value.
+ *
+ * @param queueName The quename to get from
+ * @param readTimeout The timeout to use
+ *
+ * @return the content of the text message if any
+ *
+ * @throws javax.jms.JMSException any exception that occured
+ */
+ public Message getNextMessage(String queueName, long readTimeout) throws JMSException
+ {
+ if (!connected)
+ {
+ connect();
+ }
+
+ Queue queue = session.createQueue(queueName);
+
+ final MessageConsumer consumer = session.createConsumer(queue);
+
+ Message message = consumer.receive(readTimeout);
+ session.commit();
+ consumer.close();
+
+ Message result;
+
+ // all messages we consume should be TextMessages
+ if (message instanceof TextMessage)
+ {
+ result = ((TextMessage) message);
+ }
+ else if (null == message)
+ {
+ result = null;
+ }
+ else
+ {
+ _logger.info("warning: received non-text message");
+ result = message;
+ }
+
+ return result;
+ }
+
+ /**
+ * GET the top message on a queue. Consumes the message.
+ *
+ * @param queueName The Queuename to get from
+ *
+ * @return The string content of the text message, if any received
+ *
+ * @throws javax.jms.JMSException any exception that occurs
+ */
+ public Message getNextMessage(String queueName) throws JMSException
+ {
+ return getNextMessage(queueName, 0);
+ }
+
+ /**
+ * Completely clears a queue. For readTimeout behaviour see Javadocs for javax.jms.MessageConsumer.
+ *
+ * @param queueName The Queue name to consume from
+ * @param readTimeout The timeout for each consume
+ *
+ * @throws javax.jms.JMSException Any exception that occurs during the consume
+ * @throws InterruptedException If the consume thread was interrupted during a consume.
+ */
+ public void consume(String queueName, int readTimeout) throws JMSException, InterruptedException
+ {
+ if (!connected)
+ {
+ connect();
+ }
+
+ _logger.info("consuming queue " + queueName);
+ Queue queue = session.createQueue(queueName);
+
+ final MessageConsumer consumer = session.createConsumer(queue);
+ int messagesReceived = 0;
+
+ _logger.info("consuming...");
+ while ((consumer.receive(readTimeout)) != null)
+ {
+ messagesReceived++;
+ }
+
+ session.commit();
+ consumer.close();
+ _logger.info("consumed: " + messagesReceived);
+ }
+}