summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qpid/java/broker/bin/passwd21
-rw-r--r--qpid/java/broker/bin/qpid-server9
-rw-r--r--qpid/java/broker/bin/qpid.stop38
-rw-r--r--qpid/java/broker/bin/qpid.stopall15
-rw-r--r--qpid/java/broker/distribution/src/main/assembly/broker-bin.xml12
-rw-r--r--qpid/java/broker/etc/access1
-rw-r--r--qpid/java/broker/etc/config.xml20
-rw-r--r--qpid/java/broker/etc/jmxremote.access3
-rw-r--r--qpid/java/broker/etc/log4j.xml10
-rw-r--r--qpid/java/broker/etc/persistent_config.xml132
-rw-r--r--qpid/java/broker/etc/transient_config.xml128
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java53
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java91
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java1
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java16
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java3
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java52
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java258
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java217
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedBroker.java6
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java12
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java96
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ManagedConnection.java8
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java38
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java136
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java31
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java9
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/Passwd.java81
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java457
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java5
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java33
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java63
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessManager.java183
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java21
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java111
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java68
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java626
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java144
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/MD5PasswordFilePrincipalDatabase.java160
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java92
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java22
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java50
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java4
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java82
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java7
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java19
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java15
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java50
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedSaslServer.java105
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedServerFactory.java61
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java13
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java10
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java2
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java2
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java2
-rw-r--r--qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java61
-rw-r--r--qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java4
-rw-r--r--qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java4
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java355
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java60
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java31
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java75
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java164
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java26
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java45
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java35
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/TopicPublisherAdapter.java5
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java10
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java12
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSHeaderAdapter.java4
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java28
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java12
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties1
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java33
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties1
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java104
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java72
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQNoTransportForProtocolException.java6
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQTransportConnectionException.java10
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java95
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java16
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java2
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java60
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java30
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java2
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java109
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java13
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java16
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java76
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/testutil/Config.java2
-rw-r--r--qpid/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java3
-rw-r--r--qpid/java/common/bin/qpid-run17
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/AMQException.java58
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/configuration/PropertyException.java10
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java8
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrameDecodingException.java20
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java4
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java2
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java261
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/framing/VersionSpecificRegistry.java24
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java23
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java107
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java53
-rw-r--r--qpid/java/common/src/main/java/org/apache/qpid/url/URLHelper.java44
-rw-r--r--qpid/java/distribution/src/main/assembly/bin.xml30
-rw-r--r--qpid/java/distribution/src/main/assembly/management-eclipse-plugin.xml7
-rw-r--r--qpid/java/management/eclipse-plugin/META-INF/MANIFEST.MF3
-rw-r--r--qpid/java/management/eclipse-plugin/bin/qpidmc.bat2
-rwxr-xr-xqpid/java/management/eclipse-plugin/bin/qpidmc.sh2
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java9
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java2
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java197
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java16
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java4
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java6
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java13
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java13
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java5
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java170
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java52
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java15
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java8
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java60
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/ClientSaslFactory.java54
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java56
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/PlainSaslClient.java203
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/SaslProvider.java35
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UserPasswordCallbackHandler.java73
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java82
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java2
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java98
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java27
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java410
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java84
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java13
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java12
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java462
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java69
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/sasl/MANIFEST.MF19
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/win32/configuration/config.ini2
-rwxr-xr-xqpid/java/perftests/etc/scripts/BDB-Qpid-4.sh28
-rwxr-xr-xqpid/java/perftests/etc/scripts/BDB-Qpid.sh12
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-1.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-2.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-3.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-4.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-5.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/CTQ-Qpid-6.sh1
-rwxr-xr-xqpid/java/perftests/etc/scripts/PT-Qpid-13.sh24
-rwxr-xr-xqpid/java/perftests/etc/scripts/PT-Qpid-14.sh23
-rw-r--r--qpid/java/perftests/etc/scripts/bdb-qpid-4/device.xml98
-rw-r--r--qpid/java/perftests/etc/scripts/bdb-qpid-4/filepath.xml97
-rw-r--r--qpid/java/perftests/etc/scripts/bdb-qpid-4/noneexistantpath.xml97
-rw-r--r--qpid/java/perftests/etc/scripts/bdb-qpid-4/nopermission.xml98
-rw-r--r--qpid/java/perftests/etc/scripts/bdb-qpid-4/starpath.xml98
-rw-r--r--qpid/java/perftests/pom.xml294
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java2
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java4
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java5
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingDurableClient.java40
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java57
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/requestreply/PingPongProducer.java59
-rw-r--r--qpid/java/perftests/src/main/java/org/apache/qpid/topic/Config.java2
-rw-r--r--qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java11
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java8
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java208
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java5
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTest.java276
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnection.java268
185 files changed, 8355 insertions, 1981 deletions
diff --git a/qpid/java/broker/bin/passwd b/qpid/java/broker/bin/passwd
new file mode 100644
index 0000000000..c1bb05c082
--- /dev/null
+++ b/qpid/java/broker/bin/passwd
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+. qpid-run org.apache.qpid.server.security.Passwd "$@"
diff --git a/qpid/java/broker/bin/qpid-server b/qpid/java/broker/bin/qpid-server
index 0080209479..a2b416b12b 100644
--- a/qpid/java/broker/bin/qpid-server
+++ b/qpid/java/broker/bin/qpid-server
@@ -18,4 +18,13 @@
# under the License.
#
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-incubating.jar:$QPID_HOME/lib/bdbstore-launch.jar
+
+# Set other variables used by the qpid-run script before calling
+export JAVA=java \
+ JAVA_VM=-server \
+ JAVA_MEM=-Xmx1024m \
+ QPID_CLASSPATH=$QPID_LIBS
+
. qpid-run org.apache.qpid.server.Main "$@"
diff --git a/qpid/java/broker/bin/qpid.stop b/qpid/java/broker/bin/qpid.stop
index 1bffc8cdb8..9193d3c4e1 100644
--- a/qpid/java/broker/bin/qpid.stop
+++ b/qpid/java/broker/bin/qpid.stop
@@ -5,9 +5,9 @@
# Script checks for a given pid running PROGRAM and attempts to quit it
#
-MAX_ATTEMPTS=5
-SLEEP_DELAY=2
-PROGRAM="org.apache.qpid.server.Main"
+MAX_ATTEMPTS=1
+SLEEP_DELAY=1
+PROGRAM="DQPID"
#
@@ -15,7 +15,8 @@ PROGRAM="org.apache.qpid.server.Main"
#
printActions()
{
-ps=`ps o command p $1|grep $PROGRAM`
+#ps=`ps o command p $1|grep $PROGRAM`
+ps=`ps -o args -p $1|grep $PROGRAM`
echo "Attempting to kill: $ps"
}
@@ -36,25 +37,25 @@ quit()
kill $1
}
+#
+# Grep the ps log for the PID ($1) to ensure that it has quit
+#
+lookup()
+{
+result=`ps -o args -p $1 |grep -v grep |grep $PROGRAM |wc -l`
+}
#
# Sleep and then check then lookup the PID($1) to ensure it has quit
#
check()
{
+echo "Waiting $SLEEP_DELAY second for $1 to exit"
sleep $SLEEP_DELAY
lookup $1
}
-#
-# Grep the ps log for the PID ($1) to ensure that it has quit
-#
-lookup()
-{
-result=`ps p $1 |grep -v grep |grep $PROGRAM |wc -l`
-}
-
#
# Verify the PID($1) is available
@@ -62,7 +63,7 @@ result=`ps p $1 |grep -v grep |grep $PROGRAM |wc -l`
verifyPid()
{
lookup $1
-if [[ $result == 1 ]] ; then
+if [[ $[$result] == 1 ]] ; then
brokerspid=$1
else
echo "Unable to locate Qpid Process with PID $1"
@@ -70,8 +71,6 @@ else
fi
}
-
-
#
# Main Run
#
@@ -89,22 +88,21 @@ printActions $brokerspid
# Attempt to quit the process MAX_ATTEMPTS Times
attempt=0
-while [[ $result > 0 && $attempt < $MAX_ATTEMPTS ]] ; do
+while [[ $[$result] > 0 && $[$attempt] < $[$MAX_ATTEMPTS] ]] ; do
quit $brokerspid
check $brokerspid
attempt=$[$attempt + 1]
done
-
# Check that it has quit
-if [[ $results == 0 ]] ; then
+if [[ $[$result] == 0 ]] ; then
echo "Process quit"
exit 0
else
# Now attempt to force quit the process
attempt=0
- while [[ $result > 0 && $attempt < $MAX_ATTEMPTS ]] ; do
+ while [[ $[$result] > 0 && $[$attempt] < $[$MAX_ATTEMPTS] ]] ; do
forceQuit $brokerspid
check $brokerspid
attempt=$[$attempt + 1]
@@ -112,7 +110,7 @@ else
# Output final status
- if [[ $attempt == $MAX_ATTEMPTS ]] ; then
+ if [[ $[$result] > 0 && $[$attempt] == $[$MAX_ATTEMPTS] ]] ; then
echo "Stopped trying to kill process: $brokerspid"
echo "Attempted to stop $attempt times"
else
diff --git a/qpid/java/broker/bin/qpid.stopall b/qpid/java/broker/bin/qpid.stopall
index f6862842c9..2e762bdd50 100644
--- a/qpid/java/broker/bin/qpid.stopall
+++ b/qpid/java/broker/bin/qpid.stopall
@@ -6,17 +6,16 @@
# Utilises qpid.stop to perform the actual stopping
#
-MAX_ATTEMPTS=5
-SLEEP_DELAY=2
-PROGRAM="org.apache.qpid.server.Main"
+PROGRAM="DQPID"
#
# grep ps for instances of $PROGRAM and collect PIDs
#
lookup()
{
-pids=`ps o pid,command |grep -v grep | grep $PROGRAM | cut -d ' ' -f 1`
-result=`echo -n $pids | wc -l`
+#pids=`ps o pid,command | grep $PROGRAM | grep -v grep | cut -d ' ' -f 1`
+pids=`ps -ef |grep $USER | grep $PROGRAM | grep -v grep | awk '{print $2}'`
+result=`echo -n $pids | wc -w`
}
@@ -25,7 +24,7 @@ result=`echo -n $pids | wc -l`
#
showPids()
{
-ps p $pids
+ps -o user,pid,args -p $pids
}
@@ -35,7 +34,7 @@ ps p $pids
lookup
-if [[ $result == 0 ]] ; then
+if [[ $[$result] == 0 ]] ; then
echo "No Qpid Brokers found running under user '$USER'"
exit 0
fi
@@ -49,7 +48,7 @@ done
# Check we have quit all
lookup
-if [[ $result == 0 ]] ; then
+if [[ $[$result] == 0 ]] ; then
echo "All Qpid brokers successfully quit"
else
echo "Some brokers were not quit"
diff --git a/qpid/java/broker/distribution/src/main/assembly/broker-bin.xml b/qpid/java/broker/distribution/src/main/assembly/broker-bin.xml
index 4a7343660d..4b32630771 100644
--- a/qpid/java/broker/distribution/src/main/assembly/broker-bin.xml
+++ b/qpid/java/broker/distribution/src/main/assembly/broker-bin.xml
@@ -78,6 +78,12 @@
<fileMode>420</fileMode>
</file>
<file>
+ <source>../etc/jmxremote.access</source>
+ <outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
+ <destName>jmxremote.access</destName>
+ <fileMode>420</fileMode>
+ </file>
+ <file>
<source>../etc/log4j.xml</source>
<outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
<destName>log4j.xml</destName>
@@ -108,6 +114,12 @@
<fileMode>473</fileMode>
</file>
<file>
+ <source>../bin/passwd</source>
+ <outputDirectory>qpid-${qpid.version}/bin</outputDirectory>
+ <destName>passwd</destName>
+ <fileMode>473</fileMode>
+ </file>
+ <file>
<source>../bin/qpid-server</source>
<outputDirectory>qpid-${qpid.version}/bin</outputDirectory>
<destName>qpid-server</destName>
diff --git a/qpid/java/broker/etc/access b/qpid/java/broker/etc/access
new file mode 100644
index 0000000000..a781ed8aa9
--- /dev/null
+++ b/qpid/java/broker/etc/access
@@ -0,0 +1 @@
+guest:localhost(rw),test(rw) \ No newline at end of file
diff --git a/qpid/java/broker/etc/config.xml b/qpid/java/broker/etc/config.xml
index 3789e6fcb6..c66c2f632e 100644
--- a/qpid/java/broker/etc/config.xml
+++ b/qpid/java/broker/etc/config.xml
@@ -41,6 +41,8 @@
</connector>
<management>
<enabled>true</enabled>
+ <jmxport>8999</jmxport>
+ <security-enabled>true</security-enabled>
</management>
<advanced>
<filterchain enableExecutorPool="true"/>
@@ -63,13 +65,14 @@
</attributes>
</principal-database>
- <!--principal-database>
- <name>md5passwordfile</name>
- <class>org.apache.qpid.server.security.auth.database.MD5PasswordFilePrincipalDatabase</class>
+ <!-- Example use of Base64 encoded MD5 hashes for authentication via CRAM-MD5-Hashed
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase</class>
<attributes>
<attribute>
<name>passwordFile</name>
- <value>${conf}/md5passwd</value>
+ <value>${conf}/qpid.passwd</value>
</attribute>
</attributes>
</principal-database-->
@@ -78,6 +81,10 @@
<access>
<class>org.apache.qpid.server.security.access.AllowAll</class>
</access>
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
</security>
<virtualhosts>
@@ -85,9 +92,10 @@
<name>localhost</name>
<localhost>
<store>
- <!-- <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class> -->
+ <!-- <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/localhost-store</environment-path> -->
+
<class>org.apache.qpid.server.store.MemoryMessageStore</class>
- <environment-path>localhost-store</environment-path>
</store>
<security>
diff --git a/qpid/java/broker/etc/jmxremote.access b/qpid/java/broker/etc/jmxremote.access
new file mode 100644
index 0000000000..d1172fc197
--- /dev/null
+++ b/qpid/java/broker/etc/jmxremote.access
@@ -0,0 +1,3 @@
+admin=admin
+guest=readonly
+user=readwrite
diff --git a/qpid/java/broker/etc/log4j.xml b/qpid/java/broker/etc/log4j.xml
index 74b80c0e80..b442227607 100644
--- a/qpid/java/broker/etc/log4j.xml
+++ b/qpid/java/broker/etc/log4j.xml
@@ -44,20 +44,16 @@
<param name="backupFilesToPath" value="${QPID_WORK}/backup/log"/>
<layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
- <!--param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/-->
+ <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
- <appender name="FileAppender" class="org.apache.log4j.FileAppender">
- <param name="staticLogFileName" value="false"/>
-
+ <appender name="FileAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="${QPID_WORK}/log/${logprefix}qpid${logsuffix}.log"/>
<param name="Append" value="false"/>
<layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/>
-
+ <param name="ConversionPattern" value="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</layout>
</appender>
diff --git a/qpid/java/broker/etc/persistent_config.xml b/qpid/java/broker/etc/persistent_config.xml
new file mode 100644
index 0000000000..178a73515c
--- /dev/null
+++ b/qpid/java/broker/etc/persistent_config.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+
+ This is an example config using the BDBMessageStore available from
+ the Red Hat Messaging project at etp.108.redhat.com and distributed under GPL.
+ -->
+
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <connector>
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ <jmxport>8999</jmxport>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>localhost</name>
+ <localhost>
+ <store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdbstore/localhost-store</environment-path>
+ </store>
+
+ <security>
+ <access>
+ <class>org.apache.qpid.server.security.access.PrincipalDatabaseAccessManager</class>
+ <attributes>
+ <attribute>
+ <name>principalDatabase</name>
+ <value>passwordfile</value>
+ </attribute>
+ <attribute>
+ <name>defaultAccessManager</name>
+ <value>DenyAll</value>
+ </attribute>
+ </attributes>
+ </access>
+ </security>
+ </localhost>
+ </virtualhost>
+
+ <virtualhost>
+ <name>development</name>
+ <development>
+ <store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdbstore/development-store</environment-path>
+ </store>
+ </development>
+ </virtualhost>
+
+ <virtualhost>
+ <name>test</name>
+ <test>
+ <store>
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdbstore/test-store</environment-path>
+ </store>
+ </test>
+ </virtualhost>
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/broker/etc/transient_config.xml b/qpid/java/broker/etc/transient_config.xml
new file mode 100644
index 0000000000..164d66cd1b
--- /dev/null
+++ b/qpid/java/broker/etc/transient_config.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+
+ This is an example config file that uses the MemoryMessageStore.
+ As a result it is aimed at brokers sending transient messages.
+
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <connector>
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ <jmxport>8999</jmxport>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ <jmx>
+ <access>${conf}/jmxremote.access</access>
+ <principal-database>passwordfile</principal-database>
+ </jmx>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>localhost</name>
+ <localhost>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+
+ <security>
+ <access>
+ <class>org.apache.qpid.server.security.access.PrincipalDatabaseAccessManager</class>
+ <attributes>
+ <attribute>
+ <name>principalDatabase</name>
+ <value>passwordfile</value>
+ </attribute>
+ <attribute>
+ <name>defaultAccessManager</name>
+ <value>DenyAll</value>
+ </attribute>
+ </attributes>
+ </access>
+ </security>
+ </localhost>
+ </virtualhost>
+
+ <virtualhost>
+ <name>development</name>
+ <development>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+ </development>
+ </virtualhost>
+
+ <virtualhost>
+ <name>test</name>
+ <test>
+ <store>
+ <class>org.apache.qpid.server.store.MemoryMessageStore</class>
+ </store>
+ </test>
+ </virtualhost>
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
index 23c32aceab..d31359b019 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -1,5 +1,25 @@
/*
*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+/*
+ *
* Copyright (c) 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,8 +42,12 @@ import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
+import org.apache.commons.configuration.Configuration;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.configuration.Configurator;
+import org.apache.qpid.server.configuration.VirtualHostConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
@@ -36,9 +60,6 @@ import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.configuration.Configurator;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.commons.configuration.Configuration;
/**
* This MBean implements the broker management interface and exposes the
@@ -82,8 +103,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
* @param autoDelete
* @throws JMException
*/
- public void createNewExchange(String exchangeName, String type, boolean durable, boolean autoDelete)
- throws JMException
+ public void createNewExchange(String exchangeName, String type, boolean durable) throws JMException
{
try
{
@@ -92,7 +112,8 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
Exchange exchange = _exchangeRegistry.getExchange(new AMQShortString(exchangeName));
if (exchange == null)
{
- exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName), new AMQShortString(type), durable, autoDelete, 0);
+ exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName), new AMQShortString(type),
+ durable, false, 0);
_exchangeRegistry.registerExchange(exchange);
}
else
@@ -140,8 +161,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
* @param autoDelete
* @throws JMException
*/
- public void createNewQueue(String queueName, String owner, boolean durable,boolean autoDelete)
- throws JMException
+ public void createNewQueue(String queueName, String owner, boolean durable) throws JMException
{
AMQQueue queue = _queueRegistry.getQueue(new AMQShortString(queueName));
if (queue != null)
@@ -156,22 +176,27 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
ownerShortString = new AMQShortString(owner);
}
- queue = new AMQQueue(new AMQShortString(queueName), durable, ownerShortString, autoDelete, getVirtualHost());
+
+ queue = new AMQQueue(new AMQShortString(queueName), durable, ownerShortString, false, getVirtualHost());
if (queue.isDurable() && !queue.isAutoDelete())
{
_messageStore.createQueue(queue);
}
- Configuration virtualHostDefaultQueueConfiguration = VirtualHostConfiguration.getDefaultQueueConfiguration(queue);
+ Configuration virtualHostDefaultQueueConfiguration =
+ VirtualHostConfiguration.getDefaultQueueConfiguration(queue);
if (virtualHostDefaultQueueConfiguration != null)
{
Configurator.configure(queue, virtualHostDefaultQueueConfiguration);
}
+
_queueRegistry.registerQueue(queue);
}
catch (AMQException ex)
{
- throw new MBeanException(new JMException(ex.getMessage()),"Error in creating queue " + queueName);
+ JMException jme = new JMException(ex.getMessage());
+ jme.initCause(ex);
+ throw new MBeanException(jme, "Error in creating queue " + queueName);
}
}
@@ -202,7 +227,9 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
}
catch (AMQException ex)
{
- throw new MBeanException(new JMException(ex.getMessage()), "Error in deleting queue " + queueName);
+ JMException jme = new JMException(ex.getMessage());
+ jme.initCause(ex);
+ throw new MBeanException(jme, "Error in deleting queue " + queueName);
}
}
@@ -213,7 +240,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
// This will have a single instance for a virtual host, so not having the name property in the ObjectName
public ObjectName getObjectName() throws MalformedObjectNameException
- {
+ {
return getObjectNameForSingleInstanceMBean();
}
} // End of MBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index 1ebe5fa0a2..2e1653e69d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -472,7 +472,7 @@ public class AMQChannel
if (unacked.queue != null)
{
// Ensure message is released for redelivery
- unacked.message.release();
+ unacked.message.release(unacked.queue);
// Mark message redelivered
unacked.message.setRedelivered(true);
@@ -503,7 +503,10 @@ public class AMQChannel
{
// Ensure message is released for redelivery
- unacked.message.release();
+ if (unacked.queue != null)
+ {
+ unacked.message.release(unacked.queue);
+ }
// Mark message redelivered
unacked.message.setRedelivered(true);
@@ -672,14 +675,14 @@ public class AMQChannel
// else
// {
//release to allow it to be delivered
- msg.release();
+ msg.release(message.queue);
// Without any details from the client about what has been processed we have to mark
// all messages in the unacked map as redelivered.
msg.setRedelivered(true);
- Subscription sub = msg.getDeliveredSubscription();
+ Subscription sub = msg.getDeliveredSubscription(message.queue);
if (sub != null)
{
@@ -753,7 +756,7 @@ public class AMQChannel
// Process Messages to Requeue at the front of the queue
for (UnacknowledgedMessage message : msgToRequeue)
{
- message.message.release();
+ message.message.release(message.queue);
message.message.setRedelivered(true);
deliveryContext.deliver(message.message, message.queue, true);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
index 38a505c6c7..146d0566ce 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Main.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -36,14 +36,17 @@ import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.configuration.ConfigurationException;
+
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
+
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
import org.apache.mina.transport.socket.nio.SocketSessionConfig;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.pool.ReadWriteThreadModel;
@@ -59,7 +62,7 @@ import org.apache.qpid.url.URLSyntaxException;
* Main entry point for AMQPD.
*
*/
-@SuppressWarnings({"AccessStaticViaInstance"})
+@SuppressWarnings({ "AccessStaticViaInstance" })
public class Main
{
private static final Logger _logger = Logger.getLogger(Main.class);
@@ -74,9 +77,9 @@ public class Main
protected static class InitException extends Exception
{
- InitException(String msg)
+ InitException(String msg, Throwable cause)
{
- super(msg);
+ super(msg, cause);
}
}
@@ -97,6 +100,7 @@ public class Main
try
{
commandLine = new PosixParser().parse(options, args);
+
return true;
}
catch (ParseException e)
@@ -104,6 +108,7 @@ public class Main
System.err.println("Error: " + e.getMessage());
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("Qpid", options, true);
+
return false;
}
}
@@ -112,17 +117,26 @@ public class Main
{
Option help = new Option("h", "help", false, "print this message");
Option version = new Option("v", "version", false, "print the version information and exit");
- Option configFile = OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").
- withLongOpt("config").create("c");
- Option port = OptionBuilder.withArgName("port").hasArg().withDescription("listen on the specified port. Overrides any value in the config file").
- withLongOpt("port").create("p");
- Option bind = OptionBuilder.withArgName("bind").hasArg().withDescription("bind to the specified address. Overrides any value in the config file").
- withLongOpt("bind").create("b");
- Option logconfig = OptionBuilder.withArgName("logconfig").hasArg().withDescription("use the specified log4j xml configuration file. By " +
- "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME + " in the same directory as the configuration file").
- withLongOpt("logconfig").create("l");
- Option logwatchconfig = OptionBuilder.withArgName("logwatch").hasArg().withDescription("monitor the log file configuration file for changes. Units are seconds. " +
- "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
+ Option configFile =
+ OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config")
+ .create("c");
+ Option port =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("listen on the specified port. Overrides any value in the config file")
+ .withLongOpt("port").create("p");
+ Option bind =
+ OptionBuilder.withArgName("bind").hasArg()
+ .withDescription("bind to the specified address. Overrides any value in the config file")
+ .withLongOpt("bind").create("b");
+ Option logconfig =
+ OptionBuilder.withArgName("logconfig").hasArg()
+ .withDescription("use the specified log4j xml configuration file. By "
+ + "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME
+ + " in the same directory as the configuration file").withLongOpt("logconfig").create("l");
+ Option logwatchconfig =
+ OptionBuilder.withArgName("logwatch").hasArg()
+ .withDescription("monitor the log file configuration file for changes. Units are seconds. "
+ + "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
options.addOption(help);
options.addOption(version);
@@ -150,7 +164,7 @@ public class Main
boolean first = true;
for (ProtocolVersion pv : ProtocolVersion.getSupportedProtocolVersions())
{
- if(first)
+ if (first)
{
first = false;
}
@@ -158,9 +172,11 @@ public class Main
{
protocol.append(", ");
}
+
protocol.append(pv.getMajorVersion()).append('-').append(pv.getMinorVersion());
}
+
System.out.println(ver + " (" + protocol + ")");
}
else
@@ -186,7 +202,6 @@ public class Main
}
}
-
protected void startup() throws InitException, ConfigurationException, Exception
{
final String QpidHome = System.getProperty("QPID_HOME");
@@ -201,7 +216,7 @@ public class Main
error = error + "\nNote: Qpid_HOME is not set.";
}
- throw new InitException(error);
+ throw new InitException(error, null);
}
else
{
@@ -226,8 +241,8 @@ public class Main
_logger.info("Starting Qpid.AMQP broker");
- ConnectorConfiguration connectorConfig = ApplicationRegistry.getInstance().
- getConfiguredObject(ConnectorConfiguration.class);
+ ConnectorConfiguration connectorConfig =
+ ApplicationRegistry.getInstance().getConfiguredObject(ConnectorConfiguration.class);
ByteBuffer.setUseDirectBuffers(connectorConfig.enableDirectBuffers);
@@ -249,7 +264,7 @@ public class Main
}
catch (NumberFormatException e)
{
- throw new InitException("Invalid port: " + portStr);
+ throw new InitException("Invalid port: " + portStr, e);
}
}
@@ -264,19 +279,21 @@ public class Main
int totalVHosts = ((Collection) virtualHosts).size();
for (int vhost = 0; vhost < totalVHosts; vhost++)
{
- setupVirtualHosts(configFile.getParent() , (String)((List)virtualHosts).get(vhost));
+ setupVirtualHosts(configFile.getParent(), (String) ((List) virtualHosts).get(vhost));
}
}
else
{
- setupVirtualHosts(configFile.getParent() , (String)virtualHosts);
+ setupVirtualHosts(configFile.getParent(), (String) virtualHosts);
}
}
+
bind(port, connectorConfig);
}
- protected void setupVirtualHosts(String configFileParent, String configFilePath) throws ConfigurationException, AMQException, URLSyntaxException
+ protected void setupVirtualHosts(String configFileParent, String configFilePath)
+ throws ConfigurationException, AMQException, URLSyntaxException
{
String configVar = "${conf}";
@@ -285,7 +302,7 @@ public class Main
configFilePath = configFileParent + configFilePath.substring(configVar.length());
}
- if (configFilePath.indexOf(".xml") != -1 )
+ if (configFilePath.indexOf(".xml") != -1)
{
VirtualHostConfiguration vHostConfig = new VirtualHostConfiguration(configFilePath);
vHostConfig.performBindings();
@@ -298,11 +315,12 @@ public class Main
String[] fileNames = virtualHostDir.list();
- for (int each=0; each < fileNames.length; each++)
+ for (int each = 0; each < fileNames.length; each++)
{
if (fileNames[each].endsWith(".xml"))
{
- VirtualHostConfiguration vHostConfig = new VirtualHostConfiguration(configFilePath+"/"+fileNames[each]);
+ VirtualHostConfiguration vHostConfig =
+ new VirtualHostConfiguration(configFilePath + "/" + fileNames[each]);
vHostConfig.performBindings();
}
}
@@ -319,7 +337,7 @@ public class Main
try
{
- //IoAcceptor acceptor = new SocketAcceptor(connectorConfig.processors);
+ // IoAcceptor acceptor = new SocketAcceptor(connectorConfig.processors);
IoAcceptor acceptor = connectorConfig.createAcceptor();
SocketAcceptorConfig sconfig = (SocketAcceptorConfig) acceptor.getDefaultConfig();
SocketSessionConfig sc = (SocketSessionConfig) sconfig.getSessionConfig();
@@ -334,7 +352,7 @@ public class Main
{
sconfig.setThreadModel(ReadWriteThreadModel.getInstance());
}
-
+
if (!connectorConfig.enableSSL || !connectorConfig.sslOnly)
{
AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler();
@@ -347,6 +365,7 @@ public class Main
{
bindAddress = new InetSocketAddress(InetAddress.getByAddress(parseIP(bindAddr)), port);
}
+
acceptor.bind(bindAddress, handler, sconfig);
_logger.info("Qpid.AMQP listening on non-SSL address " + bindAddress);
}
@@ -356,8 +375,7 @@ public class Main
AMQPFastProtocolHandler handler = new AMQPProtocolProvider().getHandler();
try
{
- acceptor.bind(new InetSocketAddress(connectorConfig.sslPort),
- handler, sconfig);
+ acceptor.bind(new InetSocketAddress(connectorConfig.sslPort), handler, sconfig);
_logger.info("Qpid.AMQP listening on SSL port " + connectorConfig.sslPort);
}
catch (IOException e)
@@ -415,16 +433,17 @@ public class Main
}
catch (NumberFormatException e)
{
- System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be " +
- "a non-negative integer. Using default of zero (no watching configured");
+ System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be "
+ + "a non-negative integer. Using default of zero (no watching configured");
}
+
if (logConfigFile.exists() && logConfigFile.canRead())
{
System.out.println("Configuring logger using configuration file " + logConfigFile.getAbsolutePath());
if (logWatchTime > 0)
{
- System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every " +
- logWatchTime + " seconds");
+ System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every "
+ + logWatchTime + " seconds");
// log4j expects the watch interval in milliseconds
DOMConfigurator.configureAndWatch(logConfigFile.getAbsolutePath(), logWatchTime * 1000);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
index 4d66e37628..de3905268e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
@@ -196,6 +196,7 @@ public class DestNameExchange extends AbstractExchange
}
else
{
+ _logger.error("MESSAGE LOSS: Message should be sent on a Dead Letter Queue");
_logger.warn(msg);
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
index 14687c40ae..9052b2e81f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java
@@ -98,7 +98,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR
// If we haven't requested message to be resent to this consumer then reject it from ever getting it.
// if (!evt.getMethod().resend)
{
- message.message.reject(message.message.getDeliveredSubscription());
+ message.message.reject(message.message.getDeliveredSubscription(message.queue));
}
if (evt.getMethod().requeue)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
index 2ecb39254f..30a40c5a75 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java
@@ -33,6 +33,7 @@ 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.security.access.AccessResult;
+import org.apache.qpid.server.security.access.AccessRights;
import org.apache.log4j.Logger;
public class ConnectionOpenMethodHandler implements StateAwareMethodListener<ConnectionOpenBody>
@@ -75,23 +76,26 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
if (virtualHost == null)
{
- throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: " + virtualHostName);
+ throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'");
}
else
{
session.setVirtualHost(virtualHost);
- AccessResult result = virtualHost.getAccessManager().isAuthorized(virtualHost, session.getAuthorizedID());
+ AccessResult result = virtualHost.getAccessManager().isAuthorized(virtualHost, session.getAuthorizedID(), AccessRights.Rights.ANY);
switch (result.getStatus())
{
default:
case REFUSED:
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- "Access denied to vHost '" + virtualHostName + "' by "
- + result.getAuthorizer());
+ String error = "Any access denied to vHost '" + virtualHostName + "' by "
+ + result.getAuthorizer();
+
+ _logger.warn(error);
+
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, error);
case GRANTED:
- _logger.info("Granted access to vHost '" + virtualHostName + "' for " + session.getAuthorizedID()
+ _logger.info("Granted any access to vHost '" + virtualHostName + "' for " + session.getAuthorizedID()
+ " by '" + result.getAuthorizer() + "'");
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
index 6029a023e5..fef00942a0 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java
@@ -37,6 +37,7 @@ import org.apache.qpid.server.protocol.HeartbeatConfig;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
@@ -106,7 +107,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ConnectionStartOkMethodHandler.getConfiguredFrameSize(), // frameMax
HeartbeatConfig.getInstance().getDelay()); // heartbeat
session.writeFrame(tune);
- session.setAuthorizedID(ss.getAuthorizationID());
+ session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
disposeSaslServer(session);
break;
case CONTINUE:
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
index 6c14aae7ed..4734143497 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java
@@ -37,6 +37,7 @@ import org.apache.qpid.server.protocol.HeartbeatConfig;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.state.AMQState;
import org.apache.qpid.server.state.AMQStateManager;
import org.apache.qpid.server.state.StateAwareMethodListener;
@@ -95,7 +96,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
throw new AMQException("Authentication failed");
case SUCCESS:
_logger.info("Connected as: " + ss.getAuthorizationID());
- session.setAuthorizedID(ss.getAuthorizationID());
+ session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
index 9e0a1019f2..2e697d4564 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java
@@ -64,7 +64,6 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
private final AtomicInteger _counter = new AtomicInteger();
-
protected QueueDeclareHandler()
{
Configurator.configure(this);
@@ -92,12 +91,12 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
synchronized (queueRegistry)
{
- if (((queue = queueRegistry.getQueue(body.queue)) == null) )
+ if (((queue = queueRegistry.getQueue(body.queue)) == null))
{
- if(body.passive)
+ if (body.passive)
{
- String msg = "Queue: " + body.queue + " not found.";
- throw body.getChannelException(AMQConstant.NOT_FOUND,msg );
+ String msg = "Queue: " + body.queue + " not found on VirtualHost(" + virtualHost + ").";
+ throw body.getChannelException(AMQConstant.NOT_FOUND, msg);
}
else
{
@@ -112,13 +111,16 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
Exchange defaultExchange = exchangeRegistry.getDefaultExchange();
queue.bind(body.queue, null, defaultExchange);
- _log.info("Queue " + body.queue + " bound to default exchange");
+ _log.info("Queue " + body.queue + " bound to default exchange(" + defaultExchange.getName() + ")");
}
}
}
- else if(queue.getOwner() != null && !session.getContextKey().equals(queue.getOwner()))
+ else if (queue.getOwner() != null && !session.getContextKey().equals(queue.getOwner()))
{
- throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue, as exclusive queue with same name declared on another connection");
+ throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + body.queue + "'),"
+ + " as exclusive queue with same name "
+ + "declared on another client ID('"
+ + queue.getOwner() + "')");
}
AMQChannel channel = session.getChannel(evt.getChannelId());
@@ -138,10 +140,10 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
AMQFrame response = QueueDeclareOkBody.createAMQFrame(evt.getChannelId(),
- (byte)8, (byte)0, // AMQP version (major, minor)
- queue.getConsumerCount(), // consumerCount
- queue.getMessageCount(), // messageCount
- body.queue); // queue
+ (byte) 8, (byte) 0, // AMQP version (major, minor)
+ queue.getConsumerCount(), // consumerCount
+ queue.getMessageCount(), // messageCount
+ body.queue); // queue
_log.info("Queue " + body.queue + " declared successfully");
session.writeFrame(response);
}
@@ -162,24 +164,22 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
{
final QueueRegistry registry = virtualHost.getQueueRegistry();
AMQShortString owner = body.exclusive ? session.getContextKey() : null;
- final AMQQueue queue = new AMQQueue(body.queue, body.durable, owner, body.autoDelete, virtualHost);
+ final AMQQueue queue = new AMQQueue(body.queue, body.durable, owner, body.autoDelete, virtualHost);
final AMQShortString queueName = queue.getName();
- if(body.exclusive && !body.durable)
+ if (body.exclusive && !body.durable)
{
final AMQProtocolSession.Task deleteQueueTask =
- new AMQProtocolSession.Task()
- {
-
- public void doTask(AMQProtocolSession session) throws AMQException
+ new AMQProtocolSession.Task()
{
- if(registry.getQueue(queueName) == queue)
+ public void doTask(AMQProtocolSession session) throws AMQException
{
- queue.delete();
+ if (registry.getQueue(queueName) == queue)
+ {
+ queue.delete();
+ }
}
-
- }
- };
+ };
session.addSessionCloseTask(deleteQueueTask);
@@ -190,16 +190,14 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
session.removeSessionCloseTask(deleteQueueTask);
}
});
-
-
- }
+ }// if exclusive and not durable
Configuration virtualHostDefaultQueueConfiguration = VirtualHostConfiguration.getDefaultQueueConfiguration(queue);
if (virtualHostDefaultQueueConfiguration != null)
{
Configurator.configure(queue, virtualHostDefaultQueueConfiguration);
}
-
+
return queue;
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
index c89529f2a3..38c9e4950a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,29 +20,174 @@
*/
package org.apache.qpid.server.management;
+import java.io.IOException;
import java.lang.management.ManagementFactory;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.HashMap;
+import java.util.Map;
import javax.management.JMException;
import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.AccountNotFoundException;
+import javax.security.sasl.AuthorizeCallback;
import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser;
+
+/**
+ * This class starts up an MBeanserver. If out of the box agent is being used then there are no security features
+ * implemented. To use the security features like user authentication, turn off the jmx options in the "QPID_OPTS" env
+ * variable and use JMXMP connector server. If JMXMP connector is not available, then the standard JMXConnector will be
+ * used, which again doesn't have user authentication.
+ */
public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
private final MBeanServer _mbeanServer;
+ private Registry _rmiRegistry;
+ private JMXServiceURL _jmxURL;
- public JMXManagedObjectRegistry()
+ public JMXManagedObjectRegistry() throws AMQException
{
_log.info("Initialising managed object registry using platform MBean server");
- // we use the platform MBean server currently but this must be changed or at least be configuurable
- _mbeanServer = ManagementFactory.getPlatformMBeanServer();
+ IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+
+ // Retrieve the config parameters
+ boolean platformServer = appRegistry.getConfiguration().getBoolean("management.platform-mbeanserver", true);
+
+ _mbeanServer =
+ platformServer ? ManagementFactory.getPlatformMBeanServer()
+ : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN);
+ }
+
+
+ public void start()
+ {
+ // Check if the "QPID_OPTS" is set to use Out of the Box JMXAgent
+ if (areOutOfTheBoxJMXOptionsSet())
+ {
+ _log.info("JMX: Using the out of the box JMX Agent");
+ return;
+ }
+
+ IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
+
+ boolean security = appRegistry.getConfiguration().getBoolean("management.security-enabled", true);
+ int port = appRegistry.getConfiguration().getInt("management.jmxport", 8999);
+
+ try
+ {
+ if (security)
+ {
+ // For SASL using JMXMP
+ _jmxURL = new JMXServiceURL("jmxmp", null, port);
+
+ Map env = new HashMap();
+ Map<String, PrincipalDatabase> map = appRegistry.getDatabaseManager().getDatabases();
+ PrincipalDatabase db = null;
+
+ for (Map.Entry<String, PrincipalDatabase> entry : map.entrySet())
+ {
+ if (entry.getValue() instanceof Base64MD5PasswordFilePrincipalDatabase)
+ {
+ db = entry.getValue();
+ break;
+ }
+ else if (entry.getValue() instanceof PlainPasswordFilePrincipalDatabase)
+ {
+ db = entry.getValue();
+ }
+ }
+
+ if (db instanceof Base64MD5PasswordFilePrincipalDatabase)
+ {
+ env.put("jmx.remote.profiles", "SASL/CRAM-MD5");
+ CRAMMD5HashedInitialiser initialiser = new CRAMMD5HashedInitialiser();
+ initialiser.initialise(db);
+ env.put("jmx.remote.sasl.callback.handler", initialiser.getCallbackHandler());
+ }
+ else if (db instanceof PlainPasswordFilePrincipalDatabase)
+ {
+ env.put("jmx.remote.profiles", "SASL/PLAIN");
+ env.put("jmx.remote.sasl.callback.handler", new UserCallbackHandler(db));
+ }
+
+ // Enable the SSL security and server authentication
+ /*
+ SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
+ SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
+ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);
+ */
+
+ try
+ {
+ JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(_jmxURL, env, _mbeanServer);
+ MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance();
+ cs.setMBeanServerForwarder(mbsf);
+ cs.start();
+ _log.info("JMX: Starting JMXConnector server with SASL");
+ }
+ catch (java.net.MalformedURLException urlException)
+ {
+ // When JMXMPConnector is not available
+ // java.net.MalformedURLException: Unsupported protocol: jmxmp
+ _log.info("JMX: Starting JMXConnector server");
+ startJMXConnectorServer(port);
+ }
+ }
+ else
+ {
+ startJMXConnectorServer(port);
+ }
+ }
+ catch (Exception ex)
+ {
+ _log.error("Error in initialising Managed Object Registry." + ex.getMessage());
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Starts up an RMIRegistry at configured port and attaches a JMXConnectorServer to it.
+ *
+ * @param port
+ *
+ * @throws IOException
+ */
+ private void startJMXConnectorServer(int port) throws IOException
+ {
+ startRMIRegistry(port);
+ _jmxURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxrmi");
+ JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(_jmxURL, null, _mbeanServer);
+ cs.start();
}
public void registerObject(ManagedObject managedObject) throws JMException
{
- _mbeanServer.registerMBean(managedObject, managedObject.getObjectName());
+ _mbeanServer.registerMBean(managedObject, managedObject.getObjectName());
}
public void unregisterObject(ManagedObject managedObject) throws JMException
@@ -50,4 +195,105 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_mbeanServer.unregisterMBean(managedObject.getObjectName());
}
+ /**
+ * Checks is the "QPID_OPTS" env variable is set to use the out of the box JMXAgent.
+ *
+ * @return
+ */
+ private boolean areOutOfTheBoxJMXOptionsSet()
+ {
+ if (System.getProperty("com.sun.management.jmxremote") != null)
+ {
+ return true;
+ }
+
+ if (System.getProperty("com.sun.management.jmxremote.port") != null)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Starts the rmi registry at given port
+ *
+ * @param port
+ *
+ * @throws RemoteException
+ */
+ private void startRMIRegistry(int port) throws RemoteException
+ {
+ System.setProperty("java.rmi.server.randomIDs", "true");
+ _rmiRegistry = LocateRegistry.createRegistry(port);
+ }
+
+ // stops the RMIRegistry, if it was running and bound to a port
+ public void close() throws RemoteException
+ {
+ if (_rmiRegistry != null)
+ {
+ // Stopping the RMI registry
+ UnicastRemoteObject.unexportObject(_rmiRegistry, true);
+ }
+ }
+
+ /** This class is used for SASL enabled JMXConnector for performing user authentication. */
+ private class UserCallbackHandler implements CallbackHandler
+ {
+ private final PrincipalDatabase _principalDatabase;
+
+ protected UserCallbackHandler(PrincipalDatabase database)
+ {
+ _principalDatabase = database;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ // Retrieve callbacks
+ NameCallback ncb = null;
+ PasswordCallback pcb = null;
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ ncb = (NameCallback) callbacks[i];
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ pcb = (PasswordCallback) callbacks[i];
+ }
+ else if (callbacks[i] instanceof AuthorizeCallback)
+ {
+ ((AuthorizeCallback) callbacks[i]).setAuthorized(true);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+
+ boolean authorized = false;
+ // Process retrieval of password; can get password if username is available in NameCallback
+ if ((ncb != null) && (pcb != null))
+ {
+ String username = ncb.getDefaultName();
+ try
+ {
+ authorized = _principalDatabase.verifyPassword(username, new String(pcb.getPassword()));
+ }
+ catch (AccountNotFoundException e)
+ {
+ IOException ioe = new IOException("User not authorized. " + e);
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ if (!authorized)
+ {
+ throw new IOException("User not authorized.");
+ }
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
new file mode 100644
index 0000000000..a79d993afc
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java
@@ -0,0 +1,217 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.qpid.server.management;
+
+import org.apache.qpid.AMQException;
+import org.apache.log4j.Logger;
+
+import javax.management.remote.MBeanServerForwarder;
+import javax.management.remote.JMXPrincipal;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.JMException;
+import javax.security.auth.Subject;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.AccessControlContext;
+import java.util.Set;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FileInputStream;
+
+/**
+ * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. This implements
+ * the logic for allowing the users to invoke MBean operations and implements the restrictions for readOnly, readWrite
+ * and admin users.
+ */
+public class MBeanInvocationHandlerImpl implements InvocationHandler
+{
+ private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class);
+
+ public final static String ADMIN = "admin";
+ public final static String READWRITE = "readwrite";
+ public final static String READONLY = "readonly";
+ private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
+ private MBeanServer mbs;
+ private static Properties _userRoles = new Properties();
+
+ public static MBeanServerForwarder newProxyInstance()
+ {
+ final InvocationHandler handler = new MBeanInvocationHandlerImpl();
+ final Class[] interfaces = new Class[]{MBeanServerForwarder.class};
+
+ Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler);
+ return MBeanServerForwarder.class.cast(proxy);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ final String methodName = method.getName();
+
+ if (methodName.equals("getMBeanServer"))
+ {
+ return mbs;
+ }
+
+ if (methodName.equals("setMBeanServer"))
+ {
+ if (args[0] == null)
+ {
+ throw new IllegalArgumentException("Null MBeanServer");
+ }
+ if (mbs != null)
+ {
+ throw new IllegalArgumentException("MBeanServer object already initialized");
+ }
+ mbs = (MBeanServer) args[0];
+ return null;
+ }
+
+ // Retrieve Subject from current AccessControlContext
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+
+ // Allow operations performed locally on behalf of the connector server itself
+ if (subject == null)
+ {
+ return method.invoke(mbs, args);
+ }
+
+ if (args == null || DELEGATE.equals(args[0]))
+ {
+ return method.invoke(mbs, args);
+ }
+
+ // Restrict access to "createMBean" and "unregisterMBean" to any user
+ if (methodName.equals("createMBean") || methodName.equals("unregisterMBean"))
+ {
+ throw new SecurityException("Access denied");
+ }
+
+ // Retrieve JMXPrincipal from Subject
+ Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+ if (principals == null || principals.isEmpty())
+ {
+ throw new SecurityException("Access denied");
+ }
+
+ Principal principal = principals.iterator().next();
+ String identity = principal.getName();
+
+ // Following users can perform any operation other than "createMBean" and "unregisterMBean"
+ if (isAdmin(identity) || isAllowedToModify(identity))
+ {
+ return method.invoke(mbs, args);
+ }
+
+ // These users can only call "getAttribute" on the MBeanServerDelegate MBean
+ // Here we can add other fine grained permissions like specific method for a particular mbean
+ if (isReadOnlyUser(identity) && isReadOnlyMethod(method, args))
+ {
+ return method.invoke(mbs, args);
+ }
+
+ throw new SecurityException("Access denied");
+ }
+
+ // Initialises the user roles
+ public static void setAccessRights(Properties accessRights)
+ {
+ _userRoles = accessRights;
+ }
+
+ private boolean isAdmin(String userName)
+ {
+ if (ADMIN.equals(_userRoles.getProperty(userName)))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isAllowedToModify(String userName)
+ {
+ if (READWRITE.equals(_userRoles.getProperty(userName)))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isReadOnlyUser(String userName)
+ {
+ if (READONLY.equals(_userRoles.getProperty(userName)))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isReadOnlyMethod(Method method, Object[] args)
+ {
+ String methodName = method.getName();
+ if (methodName.equals("queryMBeans") ||
+ methodName.equals("getDefaultDomain") ||
+ methodName.equals("getMBeanInfo") ||
+ methodName.equals("getAttribute") ||
+ methodName.equals("getAttributes"))
+ {
+ return true;
+ }
+
+ if (args[0] instanceof ObjectName)
+ {
+ String mbeanMethod = (args.length > 1) ? (String) args[1] : null;
+ if (mbeanMethod == null)
+ {
+ return false;
+ }
+
+ try
+ {
+ MBeanInfo mbeanInfo = mbs.getMBeanInfo((ObjectName) args[0]);
+ if (mbeanInfo != null)
+ {
+ MBeanOperationInfo[] opInfos = mbeanInfo.getOperations();
+ for (MBeanOperationInfo opInfo : opInfos)
+ {
+ if (opInfo.getName().equals(mbeanMethod) && (opInfo.getImpact() == MBeanOperationInfo.INFO))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ catch (JMException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedBroker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedBroker.java
index b2f79b6410..45e2e91ed7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedBroker.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedBroker.java
@@ -52,8 +52,7 @@ public interface ManagedBroker
@MBeanOperation(name="createNewExchange", description="Creates a new Exchange", impact= MBeanOperationInfo.ACTION)
void createNewExchange(@MBeanOperationParameter(name="name", description="Name of the new exchange")String name,
@MBeanOperationParameter(name="ExchangeType", description="Type of the exchange")String type,
- @MBeanOperationParameter(name="durable", description="true if the Exchang should be durable")boolean durable,
- @MBeanOperationParameter(name="passive", description="true of the Exchange should be passive")boolean passive)
+ @MBeanOperationParameter(name="durable", description="true if the Exchang should be durable")boolean durable)
throws IOException, JMException;
/**
@@ -81,8 +80,7 @@ public interface ManagedBroker
@MBeanOperation(name="createNewQueue", description="Create a new Queue on the Broker server", impact= MBeanOperationInfo.ACTION)
void createNewQueue(@MBeanOperationParameter(name="queue name", description="Name of the new queue")String queueName,
@MBeanOperationParameter(name="owner", description="Owner name")String owner,
- @MBeanOperationParameter(name="durable", description="true if the queue should be durable")boolean durable,
- @MBeanOperationParameter(name="autoDelete", description="true if the queue should be auto delete") boolean autoDelete)
+ @MBeanOperationParameter(name="durable", description="true if the queue should be durable")boolean durable)
throws IOException, JMException;
/**
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
index 32298f05e3..5f9bc9ddad 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.management;
import javax.management.JMException;
+import java.rmi.RemoteException;
/**
* Handles the registration (and unregistration and so on) of managed objects.
@@ -36,7 +37,11 @@ import javax.management.JMException;
*/
public interface ManagedObjectRegistry
{
+ void start();
+
void registerObject(ManagedObject managedObject) throws JMException;
void unregisterObject(ManagedObject managedObject) throws JMException;
+
+ void close() throws RemoteException;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java
index 5b86543ea6..b4fbed6948 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java
@@ -24,6 +24,8 @@ import javax.management.JMException;
import org.apache.log4j.Logger;
+import java.rmi.RemoteException;
+
/**
* This managed object registry does not actually register MBeans. This can be used in tests when management is
* not required or when management has been disabled.
@@ -38,6 +40,11 @@ public class NoopManagedObjectRegistry implements ManagedObjectRegistry
_log.info("Management is disabled");
}
+ public void start()
+ {
+ //no-op
+ }
+
public void registerObject(ManagedObject managedObject) throws JMException
{
}
@@ -45,4 +52,9 @@ public class NoopManagedObjectRegistry implements ManagedObjectRegistry
public void unregisterObject(ManagedObject managedObject) throws JMException
{
}
+
+ public void close() throws RemoteException
+ {
+
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
index fd8fb2d5cb..2e62c2f1e4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.security.Principal;
import javax.management.JMException;
import javax.security.sasl.SaslServer;
@@ -108,7 +109,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
private VersionSpecificRegistry _registry = MainRegistry.getVersionSpecificRegistry(_protocolVersion);
private List<Integer> _closingChannelsList = new ArrayList<Integer>();
private ProtocolOutputConverter _protocolOutputConverter;
- private String _authorizedID;
+ private Principal _authorizedID;
public ManagedObject getManagedObject()
@@ -745,12 +746,12 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
return _protocolOutputConverter;
}
- public void setAuthorizedID(String authorizedID)
+ public void setAuthorizedID(Principal authorizedID)
{
_authorizedID = authorizedID;
}
- public String getAuthorizedID()
+ public Principal getAuthorizedID()
{
return _authorizedID;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
index 79421dd497..390117acf6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java
@@ -31,6 +31,8 @@ import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import java.security.Principal;
+
public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
{
@@ -165,9 +167,9 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession
public ProtocolOutputConverter getProtocolOutputConverter();
- void setAuthorizedID(String authorizedID);
+ void setAuthorizedID(Principal authorizedID);
- /** @return a username string that was used to authorized this session */
- String getAuthorizedID();
+ /** @return a Principal that was used to authorized this session */
+ Principal getAuthorizedID();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
index 5eebd4c524..66f928a70e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
@@ -1,5 +1,25 @@
/*
*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+/*
+ *
* Copyright (c) 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,14 +37,15 @@
*/
package org.apache.qpid.server.protocol;
+import java.security.Principal;
import java.util.Date;
import java.util.List;
import javax.management.JMException;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
-import javax.management.Notification;
import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
import javax.management.monitor.MonitorNotification;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
@@ -56,15 +77,17 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
{
private AMQMinaProtocolSession _session = null;
private String _name = null;
-
- //openmbean data types for representing the channel attributes
- private final static String[] _channelAtttibuteNames = {"Channel Id", "Transactional", "Default Queue", "Unacknowledged Message Count"};
- private final static String[] _indexNames = {_channelAtttibuteNames[0]};
- private final static OpenType[] _channelAttributeTypes = {SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER};
- private static CompositeType _channelType = null; // represents the data type for channel data
- private static TabularType _channelsType = null; // Data type for list of channels type
+
+ // openmbean data types for representing the channel attributes
+ private static final String[] _channelAtttibuteNames =
+ { "Channel Id", "Transactional", "Default Queue", "Unacknowledged Message Count" };
+ private static final String[] _indexNames = { _channelAtttibuteNames[0] };
+ private static final OpenType[] _channelAttributeTypes =
+ { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER };
+ private static CompositeType _channelType = null; // represents the data type for channel data
+ private static TabularType _channelsType = null; // Data type for list of channels type
private static final AMQShortString BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION =
- new AMQShortString("Broker Management Console has closed the connection.");
+ new AMQShortString("Broker Management Console has closed the connection.");
@MBeanConstructor("Creates an MBean exposing an AMQ Broker Connection")
public AMQProtocolSessionMBean(AMQMinaProtocolSession session) throws NotCompliantMBeanException, OpenDataException
@@ -72,22 +95,21 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
super(ManagedConnection.class, ManagedConnection.TYPE);
_session = session;
String remote = getRemoteAddress();
- remote = "anonymous".equals(remote) ? remote + hashCode() : remote;
+ remote = "anonymous".equals(remote) ? (remote + hashCode()) : remote;
_name = jmxEncode(new StringBuffer(remote), 0).toString();
init();
}
-
static
{
try
{
init();
}
- catch(JMException ex)
+ catch (JMException ex)
{
- // It should never occur
- System.out.println(ex.getMessage());
+ // This is not expected to ever occur.
+ throw new RuntimeException("Got JMException in static initializer.", ex);
}
}
@@ -96,26 +118,27 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
*/
private static void init() throws OpenDataException
{
- _channelType = new CompositeType("Channel", "Channel Details", _channelAtttibuteNames,
- _channelAtttibuteNames, _channelAttributeTypes);
+ _channelType =
+ new CompositeType("Channel", "Channel Details", _channelAtttibuteNames, _channelAtttibuteNames,
+ _channelAttributeTypes);
_channelsType = new TabularType("Channels", "Channels", _channelType, _indexNames);
}
public String getClientId()
{
- return _session.getContextKey() == null ? null : _session.getContextKey().toString();
+ return (_session.getContextKey() == null) ? null : _session.getContextKey().toString();
}
public String getAuthorizedId()
{
- return _session.getAuthorizedID();
+ return (_session.getAuthorizedID() != null ) ? _session.getAuthorizedID().getName() : null;
}
public String getVersion()
{
- return _session.getClientVersion() == null ? null : _session.getClientVersion().toString();
+ return (_session.getClientVersion() == null) ? null : _session.getClientVersion().toString();
}
-
+
public Date getLastIoTime()
{
return new Date(_session.getIOSession().getLastIoTime());
@@ -171,6 +194,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
{
throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
}
+
_session.commitTransactions(channel);
}
catch (AMQException ex)
@@ -194,6 +218,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
{
throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
}
+
_session.rollbackTransactions(channel);
}
catch (AMQException ex)
@@ -215,9 +240,12 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
for (AMQChannel channel : list)
{
- Object[] itemValues = {channel.getChannelId(), channel.isTransactional(),
+ Object[] itemValues =
+ {
+ channel.getChannelId(), channel.isTransactional(),
(channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getName().asString() : null,
- channel.getUnacknowledgedMessageMap().size()};
+ channel.getUnacknowledgedMessageMap().size()
+ };
CompositeData channelData = new CompositeDataSupport(_channelType, _channelAtttibuteNames, itemValues);
channelsList.put(channelData);
@@ -232,17 +260,16 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
* @throws JMException
*/
public void closeConnection() throws JMException
- {
+ {
// AMQP version change: Hardwire the version to 0-8 (major=8, minor=0)
// TODO: Connect this to the session version obtained from ProtocolInitiation for this session.
// Be aware of possible changes to parameter order as versions change.
- final AMQFrame response = ConnectionCloseBody.createAMQFrame(0,
- _session.getProtocolMajorVersion(),
- _session.getProtocolMinorVersion(), // AMQP version (major, minor)
- 0, // classId
- 0, // methodId
- AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
- BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION // replyText
+ final AMQFrame response =
+ ConnectionCloseBody.createAMQFrame(0, _session.getProtocolMajorVersion(), _session.getProtocolMinorVersion(), // AMQP version (major, minor)
+ 0, // classId
+ 0, // methodId
+ AMQConstant.REPLY_SUCCESS.getCode(), // replyCode
+ BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION // replyText
);
_session.writeFrame(response);
@@ -259,18 +286,19 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
@Override
public MBeanNotificationInfo[] getNotificationInfo()
{
- String[] notificationTypes = new String[]{MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
+ String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
String name = MonitorNotification.class.getName();
String description = "Channel count has reached threshold value";
MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
- return new MBeanNotificationInfo[]{info1};
+ return new MBeanNotificationInfo[] { info1 };
}
public void notifyClients(String notificationMsg)
{
- Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
- ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
+ Notification n =
+ new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, ++_notificationSequenceNumber,
+ System.currentTimeMillis(), notificationMsg);
_broadcaster.sendNotification(n);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ManagedConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ManagedConnection.java
index 990c4c0794..e6e713ac6d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ManagedConnection.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ManagedConnection.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.protocol;
import java.io.IOException;
import java.util.Date;
+import java.security.Principal;
import javax.management.JMException;
import javax.management.MBeanOperationInfo;
@@ -67,16 +68,17 @@ public interface ManagedConnection
/**
* Tells the total number of bytes written till now.
* @return number of bytes written.
- */
+ *
@MBeanAttribute(name="WrittenBytes", description="The total number of bytes written till now")
Long getWrittenBytes();
-
+ */
/**
* Tells the total number of bytes read till now.
* @return number of bytes read.
- */
+ *
@MBeanAttribute(name="ReadBytes", description="The total number of bytes read till now")
Long getReadBytes();
+ */
/**
* Threshold high value for no of channels. This is useful in setting notifications or
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
index d6962d28cd..b2046efee3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
@@ -25,6 +25,7 @@ import org.apache.qpid.framing.AMQBody;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
@@ -42,6 +43,8 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -78,19 +81,20 @@ public class AMQMessage
private boolean _immediate;
private AtomicBoolean _taken = new AtomicBoolean(false);
-
private TransientMessageData _transientMessageData = new TransientMessageData();
private Subscription _takenBySubcription;
-
private Set<Subscription> _rejectedBy = null;
+ private Map<AMQQueue, AtomicBoolean> _takenMap = new HashMap<AMQQueue, AtomicBoolean>();
+ private Map<AMQQueue, Subscription> _takenBySubcriptionMap = new HashMap<AMQQueue, Subscription>();
- public boolean isTaken()
+ public boolean isTaken(AMQQueue queue)
{
return _taken.get();
}
private final int hashcode = System.identityHashCode(this);
+
public String debugIdentity()
{
return "(HC:" + hashcode + " ID:" + _messageId + " Ref:" + _referenceCount.get() + ")";
@@ -203,9 +207,10 @@ public class AMQMessage
_transientMessageData.setMessagePublishInfo(info);
_taken = new AtomicBoolean(false);
+
if (_log.isDebugEnabled())
{
- _log.debug("Message(" + System.identityHashCode(this) + ") created (" + debugIdentity()+")");
+ _log.debug("Message(" + System.identityHashCode(this) + ") created (" + debugIdentity() + ")");
}
}
@@ -318,8 +323,10 @@ public class AMQMessage
// enqueuing the messages ensure that if required the destinations are recorded to a
// persistent store
+
for (AMQQueue q : _transientMessageData.getDestinationQueues())
{
+ _takenMap.put(q, new AtomicBoolean(false));
_messageHandle.enqueue(storeContext, _messageId, q);
}
@@ -356,12 +363,13 @@ public class AMQMessage
}
/**
- * Creates a long-lived reference to this message, and increments the count of such references, as an atomic operation.
+ * Creates a long-lived reference to this message, and increments the count of such references, as an atomic
+ * operation.
*/
public AMQMessage takeReference()
{
_referenceCount.incrementAndGet();
- return this;
+ return this;
}
/** Threadsafe. Increment the reference count on the message. */
@@ -378,9 +386,10 @@ public class AMQMessage
* Threadsafe. This will decrement the reference count and when it reaches zero will remove the message from the
* message store.
*
+ * @param storeContext
+ *
* @throws MessageCleanupException when an attempt was made to remove the message from the message store and that
* failed
- * @param storeContext
*/
public void decrementReference(StoreContext storeContext) throws MessageCleanupException
{
@@ -451,7 +460,7 @@ public class AMQMessage
}
- public boolean taken(Subscription sub)
+ public boolean taken(AMQQueue queue, Subscription sub)
{
if (_taken.getAndSet(true))
{
@@ -464,7 +473,7 @@ public class AMQMessage
}
}
- public void release()
+ public void release(AMQQueue queue)
{
if (_log.isTraceEnabled())
{
@@ -600,7 +609,7 @@ public class AMQMessage
for (AMQQueue q : destinationQueues)
{
//Increment the references to this message for each queue delivery.
- incrementReference();
+ incrementReference();
//normal deliver so add this message at the end.
_txnContext.deliver(this, q, false);
}
@@ -824,11 +833,14 @@ public class AMQMessage
public String toString()
{
- return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken: " +
- _taken + " by:" + _takenBySubcription;
+ return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken : " +
+ _taken + " by :" + _takenBySubcription;
+
+// return "Message[" + debugIdentity() + "]: " + _messageId + "; ref count: " + _referenceCount + "; taken for queues: " +
+// _takenMap.toString() + " by Subs:" + _takenBySubcriptionMap.toString();
}
- public Subscription getDeliveredSubscription()
+ public Subscription getDeliveredSubscription(AMQQueue queue)
{
return _takenBySubcription;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
index 7a32848c44..bbaa7379f6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -1,5 +1,25 @@
/*
*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+/*
+ *
* Copyright (c) 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +37,11 @@
*/
package org.apache.qpid.server.queue;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.Iterator;
import java.util.List;
-import java.util.Date;
-import java.text.SimpleDateFormat;
import javax.management.JMException;
import javax.management.MBeanException;
@@ -41,12 +61,14 @@ import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.apache.log4j.Logger;
+
import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.CommonContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.CommonContentHeaderProperties;
+import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.ContentChunk;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.MBeanConstructor;
@@ -73,15 +95,15 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
private AMQQueue _queue = null;
private String _queueName = null;
// OpenMBean data types for viewMessages method
- private final static String[] _msgAttributeNames = {"AMQ MessageId", "Header", "Size(bytes)", "Redelivered"};
- private static String[] _msgAttributeIndex = {_msgAttributeNames[0]};
+ private static final String[] _msgAttributeNames = { "AMQ MessageId", "Header", "Size(bytes)", "Redelivered" };
+ private static String[] _msgAttributeIndex = { _msgAttributeNames[0] };
private static OpenType[] _msgAttributeTypes = new OpenType[4]; // AMQ message attribute types.
- private static CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
- private static TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
+ private static CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
+ private static TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
// OpenMBean data types for viewMessageContent method
private static CompositeType _msgContentType = null;
- private final static String[] _msgContentAttributes = {"AMQ MessageId", "MimeType", "Encoding", "Content"};
+ private static final String[] _msgContentAttributes = { "AMQ MessageId", "MimeType", "Encoding", "Content" };
private static OpenType[] _msgContentAttributeTypes = new OpenType[4];
private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length];
@@ -95,7 +117,6 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
_queueName = jmxEncode(new StringBuffer(queue.getName()), 0).toString();
}
-
public ManagedObject getParentObject()
{
return _queue.getVirtualHost().getManagedObject();
@@ -107,10 +128,10 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
init();
}
- catch(JMException ex)
+ catch (JMException ex)
{
- // It should never occur
- System.out.println(ex.getMessage());
+ // This is not expected to ever occur.
+ throw new RuntimeException("Got JMException in static initializer.", ex);
}
}
@@ -119,19 +140,21 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
*/
private static void init() throws OpenDataException
{
- _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
- _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
- _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
- _msgContentType = new CompositeType("Message Content", "AMQ Message Content", _msgContentAttributes,
- _msgContentAttributes, _msgContentAttributeTypes);
-
- _msgAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
- _msgAttributeTypes[2] = SimpleType.LONG; // For size
- _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
-
- _messageDataType = new CompositeType("Message", "AMQ Message", _msgAttributeNames, _msgAttributeNames, _msgAttributeTypes);
+ _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
+ _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
+ _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
+ _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
+ _msgContentType =
+ new CompositeType("Message Content", "AMQ Message Content", _msgContentAttributes, _msgContentAttributes,
+ _msgContentAttributeTypes);
+
+ _msgAttributeTypes[0] = SimpleType.LONG; // For message id
+ _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
+ _msgAttributeTypes[2] = SimpleType.LONG; // For size
+ _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
+
+ _messageDataType =
+ new CompositeType("Message", "AMQ Message", _msgAttributeNames, _msgAttributeNames, _msgAttributeTypes);
_messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, _msgAttributeIndex);
}
@@ -213,7 +236,8 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
public Long getMaximumQueueDepth()
{
long queueDepthInBytes = _queue.getMaximumQueueDepth();
- return queueDepthInBytes >> 10 ;
+
+ return queueDepthInBytes >> 10;
}
public void setMaximumQueueDepth(Long value)
@@ -227,7 +251,8 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
public Long getQueueDepth() throws JMException
{
long queueBytesSize = _queue.getQueueDepth();
- return queueBytesSize >> 10 ;
+
+ return queueBytesSize >> 10;
}
/**
@@ -237,13 +262,13 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
final long currentTime = System.currentTimeMillis();
- final long thresholdTime = currentTime - _queue.getMinimumAlertRepeatGap();
+ final long thresholdTime = currentTime - _queue.getMinimumAlertRepeatGap();
- for(NotificationCheck check : NotificationCheck.values())
+ for (NotificationCheck check : NotificationCheck.values())
{
- if(check.isMessageSpecific() || _lastNotificationTimes[check.ordinal()]<thresholdTime)
+ if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime))
{
- if(check.notifyIfNecessary(msg, _queue, this))
+ if (check.notifyIfNecessary(msg, _queue, this))
{
_lastNotificationTimes[check.ordinal()] = currentTime;
}
@@ -260,9 +285,10 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
// important : add log to the log file - monitoring tools may be looking for this
_logger.info(notification.name() + " On Queue " + queue.getName() + " - " + notificationMsg);
notificationMsg = notification.name() + " " + notificationMsg;
-
- _lastNotification = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
- ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
+
+ _lastNotification =
+ new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, ++_notificationSequenceNumber,
+ System.currentTimeMillis(), notificationMsg);
_broadcaster.sendNotification(_lastNotification);
}
@@ -334,20 +360,25 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
try
{
// Create header attributes list
- CommonContentHeaderProperties headerProperties = (CommonContentHeaderProperties) msg.getContentHeaderBody().properties;
+ CommonContentHeaderProperties headerProperties =
+ (CommonContentHeaderProperties) msg.getContentHeaderBody().properties;
String mimeType = null, encoding = null;
if (headerProperties != null)
{
AMQShortString mimeTypeShortSting = headerProperties.getContentType();
- mimeType = mimeTypeShortSting == null ? null : mimeTypeShortSting.toString();
- encoding = headerProperties.getEncoding() == null ? "" : headerProperties.getEncoding().toString();
+ mimeType = (mimeTypeShortSting == null) ? null : mimeTypeShortSting.toString();
+ encoding = (headerProperties.getEncoding() == null) ? "" : headerProperties.getEncoding().toString();
}
- Object[] itemValues = {msgId, mimeType, encoding, msgContent.toArray(new Byte[0])};
+
+ Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) };
+
return new CompositeDataSupport(_msgContentType, _msgContentAttributes, itemValues);
}
catch (AMQException e)
{
- throw new JMException("Error creating header attributes list: " + e);
+ JMException jme = new JMException("Error creating header attributes list: " + e);
+ jme.initCause(e);
+ throw jme;
}
}
@@ -358,8 +389,8 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
if ((beginIndex > endIndex) || (beginIndex < 1))
{
- throw new OperationsException("From Index = " + beginIndex + ", To Index = " + endIndex +
- "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
+ throw new OperationsException("From Index = " + beginIndex + ", To Index = " + endIndex
+ + "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
}
List<AMQMessage> list = _queue.getMessagesOnTheQueue();
@@ -368,20 +399,22 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
try
{
// Create the tabular list of message header contents
- for (int i = beginIndex; i <= endIndex && i <= list.size(); i++)
+ for (int i = beginIndex; (i <= endIndex) && (i <= list.size()); i++)
{
AMQMessage msg = list.get(i - 1);
ContentHeaderBody headerBody = msg.getContentHeaderBody();
// Create header attributes list
String[] headerAttributes = getMessageHeaderProperties(headerBody);
- Object[] itemValues = {msg.getMessageId(), headerAttributes, headerBody.bodySize, msg.isRedelivered()};
+ Object[] itemValues = { msg.getMessageId(), headerAttributes, headerBody.bodySize, msg.isRedelivered() };
CompositeData messageData = new CompositeDataSupport(_messageDataType, _msgAttributeNames, itemValues);
_messageList.put(messageData);
}
}
catch (AMQException e)
{
- throw new JMException("Error creating message contents: " + e);
+ JMException jme = new JMException("Error creating message contents: " + e);
+ jme.initCause(e);
+ throw jme;
}
return _messageList;
@@ -400,11 +433,11 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
list.add("JMSCorrelationID = " + headerProperties.getCorrelationIdAsString());
int delMode = headerProperties.getDeliveryMode();
- list.add("JMSDeliveryMode = " + (delMode == 1 ? "Persistent" : "Non_Persistent"));
+ list.add("JMSDeliveryMode = " + ((delMode == 1) ? "Persistent" : "Non_Persistent"));
list.add("JMSPriority = " + headerProperties.getPriority());
list.add("JMSType = " + headerProperties.getType());
-
+
long longDate = headerProperties.getExpiration();
String strDate = (longDate != 0) ? _dateFormat.format(new Date(longDate)) : null;
list.add("JMSExpiration = " + strDate);
@@ -425,27 +458,26 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
*/
public void moveMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException
{
- if (fromMessageId > toMessageId || (fromMessageId < 1))
+ if ((fromMessageId > toMessageId) || (fromMessageId < 1))
{
- throw new OperationsException("\"From MessageId\" should be greater then 0 and less then \"To MessageId\"");
+ throw new OperationsException("\"From MessageId\" should be greater then 0 and less then \"To MessageId\"");
}
_queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName, _storeContext);
}
-
/**
* returns Notifications sent by this MBean.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo()
{
- String[] notificationTypes = new String[]{MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
+ String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
String name = MonitorNotification.class.getName();
String description = "Either Message count or Queue depth or Message size has reached threshold high value";
MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
- return new MBeanNotificationInfo[]{info1};
+ return new MBeanNotificationInfo[] { info1 };
}
} // End of AMQQueueMBean class
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java
index cfa13c87fd..979f692361 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/ConcurrentSelectorDeliveryManager.java
@@ -210,6 +210,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
/**
* Returns all the messages in the Queue
+ *
* @return List of messages
*/
public List<AMQMessage> getMessages()
@@ -222,14 +223,16 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
list.add(message);
}
_lock.unlock();
-
+
return list;
}
/**
* Returns messages within the range of given messageIds
+ *
* @param fromMessageId
* @param toMessageId
+ *
* @return
*/
public List<AMQMessage> getMessages(long fromMessageId, long toMessageId)
@@ -242,7 +245,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
long maxMessageCount = toMessageId - fromMessageId + 1;
_lock.lock();
-
+
List<AMQMessage> foundMessagesList = new ArrayList<AMQMessage>();
for (AMQMessage message : _messages)
@@ -399,7 +402,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
public void removeAMessageFromTop(StoreContext storeContext) throws AMQException
{
_lock.lock();
-
+
AMQMessage message = _messages.poll();
if (message != null)
{
@@ -432,9 +435,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
return count;
}
- /**
- This can only be used to clear the _messages queue. Any subscriber resend queue will not be purged.
- */
+ /** This can only be used to clear the _messages queue. Any subscriber resend queue will not be purged. */
private AMQMessage getNextMessage() throws AMQException
{
return getNextMessage(_messages, null);
@@ -444,8 +445,12 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
{
AMQMessage message = messages.peek();
- //while (we have a message) && (The subscriber is not a browser or we are clearing) && (Check message is taken.)
- while (message != null && (sub != null && !sub.isBrowser() || sub == null) && message.taken(sub))
+ //while (we have a message) && ((The subscriber is not a browser or message is taken ) or we are clearing) && (Check message is taken.)
+ while (message != null
+ && (
+ ((sub != null && !sub.isBrowser()) || message.isTaken(_queue))
+ || sub == null)
+ && message.taken(_queue, sub))
{
//remove the already taken message
AMQMessage removed = messages.poll();
@@ -506,7 +511,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
}
if (_log.isDebugEnabled())
{
- _log.debug(debugIdentity() + "Async Delivery Message " + message.getMessageId() + "(" + System.identityHashCode(message) +
+ _log.debug(debugIdentity() + "Async Delivery Message :" + message + "(" + System.identityHashCode(message) +
") by :" + System.identityHashCode(this) +
") to :" + System.identityHashCode(sub));
}
@@ -526,7 +531,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
if (_log.isDebugEnabled())
{
- _log.debug(debugIdentity() + "Async Delivered Message r:" + removed.debugIdentity() + "d:" + message.debugIdentity() +
+ _log.debug(debugIdentity() + "Async Delivered Message r:" + removed.debugIdentity() + "d:" + message +
") by :" + System.identityHashCode(this) +
") to :" + System.identityHashCode(sub));
}
@@ -562,7 +567,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
}
catch (AMQException e)
{
- message.release();
+ message.release(_queue);
_log.error(debugIdentity() + "Unable to deliver message as dequeue failed: " + e, e);
}
}
@@ -723,7 +728,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
_log.trace(debugIdentity() + "Delivering Message:" + msg.debugIdentity() + " to(" +
System.identityHashCode(s) + ") :" + s);
}
- msg.taken(s);
+ msg.taken(_queue, s);
//Deliver the message
s.send(msg, _queue);
}
@@ -737,7 +742,7 @@ public class ConcurrentSelectorDeliveryManager implements DeliveryManager
}
}
- if (!msg.isTaken())
+ if (!msg.isTaken(_queue))
{
if (_log.isInfoEnabled())
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
index d3578d39e8..e3944954f3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
@@ -558,7 +558,7 @@ public class SubscriptionImpl implements Subscription
_logger.trace("Removed for resending:" + resent.debugIdentity());
}
- resent.release();
+ resent.release(_queue);
_queue.subscriberHasPendingResend(false, this, resent);
try
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
index 14a8063aee..89f0b7b39d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java
@@ -153,7 +153,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_logger.error("Error configuring application: " + e, e);
//throw new AMQBrokerCreationException(instanceID, "Unable to create Application Registry instance " + instanceID);
- throw new RuntimeException("Unable to create Application Registry");
+ throw new RuntimeException("Unable to create Application Registry", e);
}
}
else
@@ -168,6 +168,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
virtualHost.close();
}
+
+ // close the rmi registry(if any) started for management
+ if (getInstance().getManagedObjectRegistry() != null)
+ {
+ getInstance().getManagedObjectRegistry().close();
+ }
}
public Configuration getConfiguration()
@@ -187,7 +193,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
catch (Exception e)
{
_logger.error("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor");
- throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor");
+ throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor", e);
}
Configurator.configure(instance);
_configuredObjects.put(instanceType, instance);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
index 739ed9db42..1cca259a8d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java
@@ -42,6 +42,7 @@ import org.apache.qpid.server.security.access.AccessManager;
import org.apache.qpid.server.security.access.AccessManagerImpl;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.apache.qpid.AMQException;
public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
@@ -103,6 +104,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
public void initialise() throws Exception
{
initialiseManagedObjectRegistry();
+
_virtualHostRegistry = new VirtualHostRegistry();
_accessManager = new AccessManagerImpl("default", _configuration);
@@ -111,7 +113,12 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
_authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null);
+ _databaseManager.initialiseManagement(_configuration);
+
+ _managedObjectRegistry.start();
+
initialiseVirtualHosts();
+
}
private void initialiseVirtualHosts() throws Exception
@@ -123,7 +130,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
}
}
- private void initialiseManagedObjectRegistry()
+ private void initialiseManagedObjectRegistry() throws AMQException
{
ManagementConfiguration config = getConfiguredObject(ManagementConfiguration.class);
if (config.enabled)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Passwd.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Passwd.java
new file mode 100644
index 0000000000..f9e093dba7
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/Passwd.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security;
+
+import org.apache.commons.codec.binary.Base64;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.DigestException;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class Passwd
+{
+ public static void main(String args[]) throws NoSuchAlgorithmException, DigestException, IOException
+ {
+ if (args.length != 2)
+ {
+ System.out.println("Passwd <username> <password>");
+ System.exit(0);
+ }
+
+ byte[] data = args[1].getBytes("utf-8");
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ for (byte b : data)
+ {
+ md.update(b);
+ }
+
+ byte[] digest = md.digest();
+
+ Base64 b64 = new Base64();
+
+ byte[] encoded = b64.encode(digest);
+
+ output(args[0], encoded);
+ }
+
+ private static void output(String user, byte[] encoded) throws IOException
+ {
+
+// File passwdFile = new File("qpid.passwd");
+
+ PrintStream ps = new PrintStream(System.out);
+
+ user += ":";
+ ps.write(user.getBytes("utf-8"));
+
+ for (byte b : encoded)
+ {
+ ps.write(b);
+ }
+
+ ps.println();
+
+ ps.flush();
+ ps.close();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java
new file mode 100644
index 0000000000..a43474559d
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AMQUserManagementMBean.java
@@ -0,0 +1,457 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+import org.apache.qpid.server.management.MBeanDescription;
+import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.management.MBeanOperationParameter;
+import org.apache.qpid.server.management.MBeanOperation;
+import org.apache.qpid.server.management.MBeanInvocationHandlerImpl;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.log4j.Logger;
+import org.apache.commons.configuration.ConfigurationException;
+
+import javax.management.JMException;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.security.auth.login.AccountNotFoundException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.util.Properties;
+import java.util.List;
+import java.util.Enumeration;
+import java.util.concurrent.locks.ReentrantLock;
+import java.security.Principal;
+
+/** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */
+@MBeanDescription("User Management Interface")
+public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement
+{
+
+ private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
+
+ private PrincipalDatabase _principalDatabase;
+ private String _accessFileName;
+ private Properties _accessRights;
+ // private File _accessFile;
+ private ReentrantLock _accessRightsUpdate = new ReentrantLock();
+
+ // Setup for the TabularType
+ static TabularType _userlistDataType; // Datatype for representing User Lists
+
+ static CompositeType _userDataType; // Composite type for representing User
+ static String[] _userItemNames = {"Username", "Read", "Write", "Admin"};
+
+ static
+ {
+ String[] userItemDesc = {"Broker Login username", "Management Console Read Permission",
+ "Management Console Write Permission", "Management Console Admin Permission"};
+
+ OpenType[] userItemTypes = new OpenType[4]; // User item types.
+ userItemTypes[0] = SimpleType.STRING; // For Username
+ userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read
+ userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write
+ userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin
+ String[] userDataIndex = {_userItemNames[0]};
+
+ try
+ {
+ _userDataType =
+ new CompositeType("User", "User Data", _userItemNames, userItemDesc, userItemTypes);
+
+ _userlistDataType = new TabularType("Users", "List of users", _userDataType, userDataIndex);
+ }
+ catch (OpenDataException e)
+ {
+ _logger.error("Tabular data setup for viewing users incorrect.");
+ _userlistDataType = null;
+ }
+ }
+
+
+ public AMQUserManagementMBean() throws JMException
+ {
+ super(UserManagement.class, UserManagement.TYPE);
+ }
+
+ public String getObjectInstanceName()
+ {
+ return UserManagement.TYPE;
+ }
+
+ public boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "password", description = "Password")String password)
+ {
+ try
+ {
+ //delegate password changes to the Principal Database
+ return _principalDatabase.updatePassword(new UsernamePrincipal(username), password);
+ }
+ catch (AccountNotFoundException e)
+ {
+ _logger.warn("Attempt to set password of non-existant user'" + username + "'");
+ return false;
+ }
+ }
+
+ public boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "write", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin)
+ {
+
+ if (_accessRights.get(username) == null)
+ {
+ // If the user doesn't exist in the user rights file check that they at least have an account.
+ if (_principalDatabase.getUser(username) == null)
+ {
+ return false;
+ }
+ }
+
+ try
+ {
+
+ _accessRightsUpdate.lock();
+
+ // Update the access rights
+ if (admin)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.ADMIN);
+ }
+ else
+ {
+ if (read | write)
+ {
+ if (read)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.READONLY);
+ }
+ if (write)
+ {
+ _accessRights.put(username, MBeanInvocationHandlerImpl.READWRITE);
+ }
+ }
+ else
+ {
+ _accessRights.remove(username);
+ }
+ }
+
+ saveAccessFile();
+ }
+ finally
+ {
+ if (_accessRightsUpdate.isHeldByCurrentThread())
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
+
+ return true;
+ }
+
+ public boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "password", description = "Password")String password,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "write", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin)
+ {
+ if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password))
+ {
+ _accessRights.put(username, "");
+
+ return setRights(username, read, write, admin);
+ }
+
+ return false;
+ }
+
+ public boolean deleteUser(@MBeanOperationParameter(name = "username", description = "Username")String username)
+ {
+
+ try
+ {
+ if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username)))
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ _accessRights.remove(username);
+ saveAccessFile();
+ }
+ finally
+ {
+ if (_accessRightsUpdate.isHeldByCurrentThread())
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
+ return true;
+ }
+ }
+ catch (AccountNotFoundException e)
+ {
+ _logger.warn("Attempt to delete user (" + username + ") that doesn't exist");
+ }
+
+ return false;
+ }
+
+ public boolean reloadData()
+ {
+ try
+ {
+ try
+ {
+ loadAccessFile();
+ }
+ catch (ConfigurationException e)
+ {
+ _logger.info("Reload failed due to:" + e);
+ return false;
+ }
+
+ // Reload successful
+ return true;
+ }
+ catch (IOException e)
+ {
+ _logger.info("Reload failed due to:" + e);
+ // Reload unsuccessful
+ return false;
+ }
+ }
+
+
+ @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.")
+ public TabularData viewUsers()
+ {
+ // Table of users
+ // Username(string), Access rights Read,Write,Admin(bool,bool,bool)
+
+ reloadData();
+
+ if (_userlistDataType == null)
+ {
+ _logger.warn("TabluarData not setup correctly");
+ return null;
+ }
+
+ List<Principal> users = _principalDatabase.getUsers();
+
+ TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
+
+ try
+ {
+ // Create the tabular list of message header contents
+ for (Principal user : users)
+ {
+ // Create header attributes list
+
+ String rights = (String) _accessRights.get(user.getName());
+
+ Boolean read = false;
+ Boolean write = false;
+ Boolean admin = false;
+
+ if (rights != null)
+ {
+ read = rights.equals(MBeanInvocationHandlerImpl.READONLY)
+ || rights.equals(MBeanInvocationHandlerImpl.READWRITE);
+ write = rights.equals(MBeanInvocationHandlerImpl.READWRITE);
+ admin = rights.equals(MBeanInvocationHandlerImpl.ADMIN);
+ }
+
+ Object[] itemData = {user.getName(), read, write, admin};
+ CompositeData messageData = new CompositeDataSupport(_userDataType, _userItemNames, itemData);
+ userList.put(messageData);
+ }
+ }
+ catch (OpenDataException e)
+ {
+ _logger.warn("Unable to create user list due to :" + e);
+ return null;
+ }
+
+ return userList;
+ }
+
+ /*** Broker Methods **/
+
+ /**
+ * setPrincipalDatabase
+ *
+ * @param database set The Database to use for user lookup
+ */
+ public void setPrincipalDatabase(PrincipalDatabase database)
+ {
+ _principalDatabase = database;
+ }
+
+ /**
+ * setAccessFile
+ *
+ * @param accessFile the file to use for updating.
+ *
+ * @throws java.io.IOException If the file cannot be accessed
+ * @throws org.apache.commons.configuration.ConfigurationException
+ * if checks on the file fail.
+ */
+ public void setAccessFile(String accessFile) throws IOException, ConfigurationException
+ {
+ _accessFileName = accessFile;
+
+ if (_accessFileName != null)
+ {
+ loadAccessFile();
+ }
+ else
+ {
+ _logger.warn("Access rights file specified is null. Access rights not changed.");
+ }
+ }
+
+ private void loadAccessFile() throws IOException, ConfigurationException
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+
+ Properties accessRights = new Properties();
+
+ File accessFile = new File(_accessFileName);
+
+ if (!accessFile.exists())
+ {
+ throw new ConfigurationException("'" + _accessFileName + "' does not exist");
+ }
+
+ if (!accessFile.canRead())
+ {
+ throw new ConfigurationException("Cannot read '" + _accessFileName + "'.");
+ }
+
+ if (!accessFile.canWrite())
+ {
+ _logger.warn("Unable to write to access file '" + _accessFileName + "' changes will not be preserved.");
+ }
+
+ accessRights.load(new FileInputStream(accessFile));
+ checkAccessRights(accessRights);
+ setAccessRights(accessRights);
+ }
+ finally
+ {
+ if (_accessRightsUpdate.isHeldByCurrentThread())
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
+ }
+
+ private void checkAccessRights(Properties accessRights)
+ {
+ Enumeration values = accessRights.propertyNames();
+
+ while (values.hasMoreElements())
+ {
+ String user = (String) values.nextElement();
+
+ if (_principalDatabase.getUser(user) == null)
+ {
+ _logger.warn("Access rights contains user '" + user + "' but there is no authentication data for that user");
+ }
+ }
+ }
+
+ private void saveAccessFile()
+ {
+ try
+ {
+ _accessRightsUpdate.lock();
+ try
+ {
+ // remove old temporary file
+ File tmp = new File(_accessFileName + ".tmp");
+ if (tmp.exists())
+ {
+ tmp.delete();
+ }
+
+ //remove old backup
+ File old = new File(_accessFileName + ".old");
+ if (old.exists())
+ {
+ old.delete();
+ }
+
+ // Rename current file
+ File rights = new File(_accessFileName);
+ rights.renameTo(old);
+
+ FileOutputStream output = new FileOutputStream(tmp);
+ _accessRights.store(output, "");
+ output.close();
+
+ // Rename new file to main file
+ tmp.renameTo(rights);
+
+ // delete tmp
+ tmp.delete();
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Problem occured saving '" + _accessFileName + "' changes may not be preserved. :" + e);
+ }
+ }
+ finally
+ {
+ if (_accessRightsUpdate.isHeldByCurrentThread())
+ {
+ _accessRightsUpdate.unlock();
+ }
+ }
+ }
+
+ /**
+ * user=read user=write user=readwrite user=admin
+ *
+ * @param accessRights The properties list of access rights to process
+ */
+ private void setAccessRights(Properties accessRights)
+ {
+ _logger.debug("Setting Access Rights:" + accessRights);
+ _accessRights = accessRights;
+ MBeanInvocationHandlerImpl.setAccessRights(_accessRights);
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java
index 0c0de88182..d70a6dc8f4 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManager.java
@@ -20,8 +20,13 @@
*/
package org.apache.qpid.server.security.access;
+import java.security.Principal;
+
public interface AccessManager
{
+ AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights);
+
+ @Deprecated
AccessResult isAuthorized(Accessable accessObject, String username);
String getName();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java
index 0feb2791da..35d036d20f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessManagerImpl.java
@@ -23,13 +23,13 @@ package org.apache.qpid.server.security.access;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.configuration.PropertyUtils;
-import org.apache.qpid.configuration.PropertyException;
import org.apache.log4j.Logger;
import java.util.List;
import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
+import java.security.Principal;
public class AccessManagerImpl implements AccessManager
{
@@ -39,8 +39,13 @@ public class AccessManagerImpl implements AccessManager
public AccessManagerImpl(String name, Configuration hostConfig) throws ConfigurationException
{
- String accessClass = hostConfig.getString("security.access.class");
+ if (hostConfig == null)
+ {
+ _logger.warn("No Configuration specified. Using default access controls for VirtualHost:'" + name + "'");
+ return;
+ }
+ String accessClass = hostConfig.getString("security.access.class");
if (accessClass == null)
{
_logger.warn("No access control specified. Using default access controls for VirtualHost:'" + name + "'");
@@ -111,21 +116,35 @@ public class AccessManagerImpl implements AccessManager
}
catch (Exception e)
{
- throw new ConfigurationException(e.getCause());
+ ConfigurationException ce = new ConfigurationException(e.getMessage(), e.getCause());
+ ce.initCause(e);
+ throw ce;
}
}
}
-
public AccessResult isAuthorized(Accessable accessObject, String username)
{
+ return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ);
+ }
+
+ public AccessResult isAuthorized(Accessable accessObject, Principal user, AccessRights.Rights rights)
+ {
if (_accessManager == null)
{
- return ApplicationRegistry.getInstance().getAccessManager().isAuthorized(accessObject, username);
+ if (ApplicationRegistry.getInstance().getAccessManager() == this)
+ {
+ _logger.warn("No Default access manager specified DENYING ALL ACCESS");
+ return new AccessResult(this, AccessResult.AccessStatus.REFUSED);
+ }
+ else
+ {
+ return ApplicationRegistry.getInstance().getAccessManager().isAuthorized(accessObject, user, rights);
+ }
}
else
{
- return _accessManager.isAuthorized(accessObject, username);
+ return _accessManager.isAuthorized(accessObject, user, rights);
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java
new file mode 100644
index 0000000000..1b79a5a0e0
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AccessRights.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+public class AccessRights
+{
+ public enum Rights
+ {
+ ANY,
+ READ,
+ WRITE,
+ READWRITE
+ }
+
+ Rights _right;
+
+ public AccessRights(Rights right)
+ {
+ _right = right;
+ }
+
+ public boolean allows(Rights rights)
+ {
+ switch (_right)
+ {
+ case ANY:
+ return (rights.equals(Rights.WRITE)
+ || rights.equals(Rights.READ)
+ || rights.equals(Rights.READWRITE)
+ || rights.equals(Rights.ANY));
+ case READ:
+ return rights.equals(Rights.READ) || rights.equals(Rights.ANY);
+ case WRITE:
+ return rights.equals(Rights.WRITE) || rights.equals(Rights.ANY);
+ case READWRITE:
+ return true;
+ }
+ return false;
+ }
+
+ public Rights getRights()
+ {
+ return _right;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java
index b2e4094edd..1ddca3a64e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/AllowAll.java
@@ -20,9 +20,16 @@
*/
package org.apache.qpid.server.security.access;
+import java.security.Principal;
+
public class AllowAll implements AccessManager
{
+ public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights)
+ {
+ return new AccessResult(this, AccessResult.AccessStatus.GRANTED);
+ }
+
public AccessResult isAuthorized(Accessable accessObject, String username)
{
return new AccessResult(this, AccessResult.AccessStatus.GRANTED);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java
index 0e62d2657f..bf40eeba4e 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/DenyAll.java
@@ -20,8 +20,15 @@
*/
package org.apache.qpid.server.security.access;
+import java.security.Principal;
+
public class DenyAll implements AccessManager
{
+ public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights)
+ {
+ return new AccessResult(this, AccessResult.AccessStatus.REFUSED);
+ }
+
public AccessResult isAuthorized(Accessable accessObject, String username)
{
return new AccessResult(this, AccessResult.AccessStatus.REFUSED);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessManager.java
new file mode 100644
index 0000000000..291bc714ed
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/FileAccessManager.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.log4j.Logger;
+
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.File;
+import java.util.regex.Pattern;
+import java.security.Principal;
+
+/**
+ * Represents a user database where the account information is stored in a simple flat file.
+ *
+ * The file is expected to be in the form: username:password username1:password1 ... usernamen:passwordn
+ *
+ * where a carriage return separates each username/password pair. Passwords are assumed to be in plain text.
+ */
+public class FileAccessManager implements AccessManager
+{
+ private static final Logger _logger = Logger.getLogger(FileAccessManager.class);
+
+ protected File _accessFile;
+
+ protected Pattern _regexp = Pattern.compile(":");
+
+ private static final short USER_INDEX = 0;
+ private static final short VIRTUALHOST_INDEX = 1;
+
+ public void setAccessFile(String accessFile) throws FileNotFoundException
+ {
+ File f = new File(accessFile);
+ _logger.info("FileAccessManager using file " + f.getAbsolutePath());
+ _accessFile = f;
+ if (!f.exists())
+ {
+ throw new FileNotFoundException("Cannot find access file " + f);
+ }
+ if (!f.canRead())
+ {
+ throw new FileNotFoundException("Cannot read access file " + f +
+ ". Check permissions.");
+ }
+ }
+
+ /**
+ * Looks up the virtual hosts for a specified user in the access file.
+ *
+ * @param user The user to lookup
+ *
+ * @return a list of virtualhosts
+ */
+ private VirtualHostAccess[] lookupVirtualHost(String user)
+ {
+ String[] results = lookup(user, VIRTUALHOST_INDEX);
+ VirtualHostAccess vhosts[] = new VirtualHostAccess[results.length];
+
+ for (int index = 0; index < results.length; index++)
+ {
+ vhosts[index] = new VirtualHostAccess(results[index]);
+ }
+
+ return vhosts;
+ }
+
+
+ private String[] lookup(String user, int index)
+ {
+ try
+ {
+ BufferedReader reader = null;
+ try
+ {
+ reader = new BufferedReader(new FileReader(_accessFile));
+ String line;
+
+ while ((line = reader.readLine()) != null)
+ {
+ String[] result = _regexp.split(line);
+ if (result == null || result.length < (index + 1))
+ {
+ continue;
+ }
+
+ if (user.equals(result[USER_INDEX]))
+ {
+ return result[index].split(",");
+ }
+ }
+ return null;
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ //ignore
+ }
+ return null;
+ }
+
+ public AccessResult isAuthorized(Accessable accessObject, String username)
+ {
+ return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ);
+ }
+
+ public AccessResult isAuthorized(Accessable accessObject, Principal user, AccessRights.Rights rights)
+ {
+ if (accessObject instanceof VirtualHost)
+ {
+ VirtualHostAccess[] hosts = lookupVirtualHost(user.getName());
+
+ if (hosts != null)
+ {
+ for (VirtualHostAccess host : hosts)
+ {
+ if (accessObject.getAccessableName().equals(host.getVirtualHost()))
+ {
+ if (host.getAccessRights().allows(rights))
+ {
+ return new AccessResult(this, AccessResult.AccessStatus.GRANTED);
+ }
+ else
+ {
+ return new AccessResult(this, AccessResult.AccessStatus.REFUSED);
+ }
+ }
+ }
+ }
+ }
+// else if (accessObject instanceof AMQQueue)
+// {
+// String[] queues = lookupQueue(username, ((AMQQueue) accessObject).getVirtualHost());
+//
+// if (queues != null)
+// {
+// for (String queue : queues)
+// {
+// if (accessObject.getAccessableName().equals(queue))
+// {
+// return new AccessResult(this, AccessResult.AccessStatus.GRANTED);
+// }
+// }
+// }
+// }
+
+ return new AccessResult(this, AccessResult.AccessStatus.REFUSED);
+ }
+
+ public String getName()
+ {
+ return "FileAccessManager";
+ }
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java
index 0e447b5744..6ccadb2e7d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalDatabaseAccessManager.java
@@ -22,8 +22,11 @@ package org.apache.qpid.server.security.access;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.log4j.Logger;
+import java.security.Principal;
+
public class PrincipalDatabaseAccessManager implements AccessManager
{
private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAccessManager.class);
@@ -58,15 +61,21 @@ public class PrincipalDatabaseAccessManager implements AccessManager
}
}
+
public AccessResult isAuthorized(Accessable accessObject, String username)
{
+ return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ);
+ }
+
+ public AccessResult isAuthorized(Accessable accessObject, Principal username, AccessRights.Rights rights)
+ {
AccessResult result;
if (_database == null)
{
if (_default != null)
{
- result = _default.isAuthorized(accessObject, username);
+ result = _default.isAuthorized(accessObject, username, rights);
}
else
{
@@ -75,7 +84,15 @@ public class PrincipalDatabaseAccessManager implements AccessManager
}
else
{
- result = ((AccessManager) _database).isAuthorized(accessObject, username);
+ if (!(_database instanceof AccessManager))
+ {
+ _logger.warn("Specified PrincipalDatabase is not an AccessManager so using default AccessManager");
+ result = _default.isAuthorized(accessObject, username, rights);
+ }
+ else
+ {
+ result = ((AccessManager) _database).isAuthorized(accessObject, username, rights);
+ }
}
result.addAuthorizer(this);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java
new file mode 100644
index 0000000000..6381213398
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/UserManagement.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+import org.apache.qpid.server.management.MBeanOperation;
+import org.apache.qpid.server.management.MBeanOperationParameter;
+import org.apache.qpid.server.management.MBeanAttribute;
+import org.apache.qpid.AMQException;
+
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.CompositeData;
+import javax.management.JMException;
+import java.io.IOException;
+
+public interface UserManagement
+{
+ String TYPE = "UserManagement";
+
+ //********** Operations *****************//
+ /**
+ * set password for user
+ *
+ * @param username The username to create
+ * @param password The password for the user
+ *
+ * @return The result of the operation
+ */
+ @MBeanOperation(name = "setPassword", description = "Set password for user.")
+ boolean setPassword(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "password", description = "Password")String password);
+
+ /**
+ * set rights for users with given details
+ *
+ * @param username The username to create
+ * @param read The set of permission to give the new user
+ * @param write The set of permission to give the new user
+ * @param admin The set of permission to give the new user
+ *
+ * @return The result of the operation
+ */
+ @MBeanOperation(name = "setRights", description = "Set access rights for user.")
+ boolean setRights(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "write", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
+
+ /**
+ * Create users with given details
+ *
+ * @param username The username to create
+ * @param password The password for the user
+ * @param read The set of permission to give the new user
+ * @param write The set of permission to give the new user
+ * @param admin The set of permission to give the new user
+ *
+ * @return The result of the operation
+ */
+ @MBeanOperation(name = "createUser", description = "Create new user from system.")
+ boolean createUser(@MBeanOperationParameter(name = "username", description = "Username")String username,
+ @MBeanOperationParameter(name = "password", description = "Password")String password,
+ @MBeanOperationParameter(name = "read", description = "Administration read")boolean read,
+ @MBeanOperationParameter(name = "write", description = "Administration write")boolean write,
+ @MBeanOperationParameter(name = "admin", description = "Administration rights")boolean admin);
+
+ /**
+ * View users returns all the users that are currently available to the system.
+ *
+ * @param username The user to delete
+ *
+ * @return The result of the operation
+ */
+ @MBeanOperation(name = "deleteUser", description = "Delete user from system.")
+ boolean deleteUser(@MBeanOperationParameter(name = "username", description = "Username")String username);
+
+
+ /**
+ * Reload the date from disk
+ *
+ * @return The result of the operation
+ */
+// @MBeanOperation(name = "reloadData", description = "Reload the authentication file from disk.")
+// boolean reloadData();
+
+ /**
+ * View users returns all the users that are currently available to the system.
+ *
+ * @return a table of users data (Username, read, write, admin)
+ */
+ @MBeanOperation(name = "viewUsers", description = "All users with access rights to the system.")
+ TabularData viewUsers();
+
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java
new file mode 100644
index 0000000000..13151a66b8
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/VirtualHostAccess.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.access;
+
+public class VirtualHostAccess
+{
+ private String _vhost;
+ private AccessRights _rights;
+
+ public VirtualHostAccess(String vhostaccess)
+ {
+ //format <vhost>(<rights>)
+ int hostend = vhostaccess.indexOf('(');
+
+ if (hostend == -1)
+ {
+ throw new IllegalArgumentException("VirtualHostAccess format string contains no access _rights");
+ }
+
+ _vhost = vhostaccess.substring(0, hostend);
+
+ String rights = vhostaccess.substring(hostend);
+
+ if (rights.indexOf('r') != -1)
+ {
+ if (rights.indexOf('w') != -1)
+ {
+ _rights = new AccessRights(AccessRights.Rights.READWRITE);
+ }
+ else
+ {
+ _rights = new AccessRights(AccessRights.Rights.READ);
+ }
+ }
+ else if (rights.indexOf('w') != -1)
+ {
+ _rights = new AccessRights(AccessRights.Rights.WRITE);
+ }
+ }
+
+ public AccessRights getAccessRights()
+ {
+ return _rights;
+ }
+
+ public String getVirtualHost()
+ {
+ return _vhost;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
new file mode 100644
index 0000000000..956db64d90
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabase.java
@@ -0,0 +1,626 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.auth.database;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5HashedInitialiser;
+import org.apache.qpid.server.security.access.AMQUserManagementMBean;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.EncoderException;
+
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.AccountNotFoundException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.UnsupportedEncodingException;
+import java.io.PrintStream;
+import java.util.regex.Pattern;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.concurrent.locks.ReentrantLock;
+import java.security.Principal;
+import java.security.NoSuchAlgorithmException;
+import java.security.MessageDigest;
+
+/**
+ * Represents a user database where the account information is stored in a simple flat file.
+ *
+ * The file is expected to be in the form: username:password username1:password1 ... usernamen:passwordn
+ *
+ * where a carriage return separates each username/password pair. Passwords are assumed to be in plain text.
+ */
+public class Base64MD5PasswordFilePrincipalDatabase implements PrincipalDatabase
+{
+ private static final Logger _logger = Logger.getLogger(Base64MD5PasswordFilePrincipalDatabase.class);
+
+ private File _passwordFile;
+
+ private Pattern _regexp = Pattern.compile(":");
+
+ private Map<String, AuthenticationProviderInitialiser> _saslServers;
+
+ AMQUserManagementMBean _mbean;
+ private static final String DEFAULT_ENCODING = "utf-8";
+ private Map<String, User> _users = new HashMap<String, User>();
+ private ReentrantLock _userUpdate = new ReentrantLock();
+
+ public Base64MD5PasswordFilePrincipalDatabase()
+ {
+ _saslServers = new HashMap<String, AuthenticationProviderInitialiser>();
+
+ /**
+ * Create Authenticators for MD5 Password file.
+ */
+
+ // Accept Plain incomming and hash it for comparison to the file.
+ CRAMMD5HashedInitialiser cram = new CRAMMD5HashedInitialiser();
+ cram.initialise(this);
+ _saslServers.put(cram.getMechanismName(), cram);
+
+ //fixme The PDs should setup a PD Mangement MBean
+// try
+// {
+// _mbean = new AMQUserManagementMBean();
+// _mbean.setPrincipalDatabase(this);
+// }
+// catch (JMException e)
+// {
+// _logger.warn("User management disabled as unable to create MBean:" + e);
+// }
+ }
+
+ public void setPasswordFile(String passwordFile) throws IOException
+ {
+ File f = new File(passwordFile);
+ _logger.info("PasswordFilePrincipalDatabase using file " + f.getAbsolutePath());
+ _passwordFile = f;
+ if (!f.exists())
+ {
+ throw new FileNotFoundException("Cannot find password file " + f);
+ }
+ if (!f.canRead())
+ {
+ throw new FileNotFoundException("Cannot read password file " + f +
+ ". Check permissions.");
+ }
+
+ loadPasswordFile();
+ }
+
+ /**
+ * SASL Callback Mechanism - sets the Password in the PasswordCallback based on the value in the PasswordFile
+ *
+ * @param principal The Principal to set the password for
+ * @param callback The PasswordCallback to call setPassword on
+ *
+ * @throws AccountNotFoundException If the Principal cannont be found in this Database
+ */
+ public void setPassword(Principal principal, PasswordCallback callback) throws AccountNotFoundException
+ {
+ if (_passwordFile == null)
+ {
+ throw new AccountNotFoundException("Unable to locate principal since no password file was specified during initialisation");
+ }
+ if (principal == null)
+ {
+ throw new IllegalArgumentException("principal must not be null");
+ }
+
+ char[] pwd = lookupPassword(principal.getName());
+
+ if (pwd != null)
+ {
+ callback.setPassword(pwd);
+ }
+ else
+ {
+ throw new AccountNotFoundException("No account found for principal " + principal);
+ }
+ }
+
+ /**
+ * Used to verify that the presented Password is correct. Currently only used by Management Console
+ *
+ * @param principal The principal to authenticate
+ * @param password The password to check
+ *
+ * @return true if password is correct
+ *
+ * @throws AccountNotFoundException if the principal cannot be found
+ */
+ public boolean verifyPassword(String principal, String password) throws AccountNotFoundException
+ {
+ try
+ {
+ char[] pwd = lookupPassword(principal);
+ byte[] passwordBytes = password.getBytes(DEFAULT_ENCODING);
+
+ int index = 0;
+ boolean verified = true;
+
+ while (verified & index < passwordBytes.length)
+ {
+ verified = (pwd[index] == (char) passwordBytes[index]);
+ index++;
+ }
+ return verified;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return false;
+ }
+ }
+
+ public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException
+ {
+ User user = _users.get(principal.getName());
+
+ if (user == null)
+ {
+ throw new AccountNotFoundException(principal.getName());
+ }
+
+ try
+ {
+
+ char[] passwd = convertPassword(password);
+
+ try
+ {
+ _userUpdate.lock();
+ user.setPassword(passwd);
+
+ try
+ {
+ savePasswordFile();
+ }
+ catch (IOException e)
+ {
+ _logger.error("Unable to save password file, password change for user'"
+ + principal + "' will revert at restart");
+ return false;
+ }
+ return true;
+ }
+ finally
+ {
+ if (_userUpdate.isHeldByCurrentThread())
+ {
+ _userUpdate.unlock();
+ }
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return false;
+ }
+ }
+
+ private char[] convertPassword(String password) throws UnsupportedEncodingException
+ {
+ byte[] passwdBytes = password.getBytes(DEFAULT_ENCODING);
+
+ char[] passwd = new char[passwdBytes.length];
+
+ int index = 0;
+
+ for (byte b : passwdBytes)
+ {
+ passwd[index++] = (char) b;
+ }
+
+ return passwd;
+ }
+
+ public boolean createPrincipal(Principal principal, String password)
+ {
+ if (_users.get(principal.getName()) != null)
+ {
+ return false;
+ }
+
+ User user;
+ try
+ {
+ user = new User(principal.getName(), convertPassword(password));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ _logger.warn("Unable to encode password:" + e);
+ return false;
+ }
+
+ try
+ {
+ _userUpdate.lock();
+ _users.put(user.getName(), user);
+
+ try
+ {
+ savePasswordFile();
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+
+ }
+ finally
+ {
+ if (_userUpdate.isHeldByCurrentThread())
+ {
+ _userUpdate.unlock();
+ }
+ }
+ }
+
+ public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
+ {
+ User user = _users.get(principal.getName());
+
+ if (user == null)
+ {
+ throw new AccountNotFoundException(principal.getName());
+ }
+
+ try
+ {
+ _userUpdate.lock();
+ user.delete();
+
+ try
+ {
+ savePasswordFile();
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Unable to remove user '" + user.getName() + "' from password file.");
+ return false;
+ }
+
+ _users.remove(user.getName());
+ }
+ finally
+ {
+ if (_userUpdate.isHeldByCurrentThread())
+ {
+ _userUpdate.unlock();
+ }
+ }
+
+ return true;
+ }
+
+
+ public Map<String, AuthenticationProviderInitialiser> getMechanisms()
+ {
+ return _saslServers;
+ }
+
+ public List<Principal> getUsers()
+ {
+ return new LinkedList<Principal>(_users.values());
+ }
+
+ public Principal getUser(String username)
+ {
+ if (_users.containsKey(username))
+ {
+ return new UsernamePrincipal(username);
+ }
+ return null;
+ }
+
+ /**
+ * Looks up the password for a specified user in the password file. Note this code is <b>not</b> secure since it
+ * creates strings of passwords. It should be modified to create only char arrays which get nulled out.
+ *
+ * @param name The principal name to lookup
+ *
+ * @return a char[] for use in SASL.
+ */
+ private char[] lookupPassword(String name)
+ {
+ User user = _users.get(name);
+ if (user == null)
+ {
+ return null;
+ }
+ else
+ {
+ return user.getPassword();
+ }
+ }
+
+
+ private void loadPasswordFile() throws IOException
+ {
+ try
+ {
+ _userUpdate.lock();
+ _users.clear();
+
+ BufferedReader reader = null;
+ try
+ {
+ reader = new BufferedReader(new FileReader(_passwordFile));
+ String line;
+
+ while ((line = reader.readLine()) != null)
+ {
+ String[] result = _regexp.split(line);
+ if (result == null || result.length < 2 || result[0].startsWith("#"))
+ {
+ continue;
+ }
+
+ User user = new User(result);
+ _logger.info("Created user:" + user);
+ _users.put(user.getName(), user);
+ }
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ reader.close();
+ }
+ }
+ }
+ finally
+ {
+ if (_userUpdate.isHeldByCurrentThread())
+ {
+ _userUpdate.unlock();
+ }
+ }
+ }
+
+ private void savePasswordFile() throws IOException
+ {
+ try
+ {
+ _userUpdate.lock();
+
+ BufferedReader reader = null;
+ PrintStream writer = null;
+ File tmp = new File(_passwordFile.getAbsolutePath() + ".tmp");
+ if (tmp.exists())
+ {
+ tmp.delete();
+ }
+ try
+ {
+ writer = new PrintStream(tmp);
+ reader = new BufferedReader(new FileReader(_passwordFile));
+ String line;
+
+ while ((line = reader.readLine()) != null)
+ {
+ String[] result = _regexp.split(line);
+ if (result == null || result.length < 2 || result[0].startsWith("#"))
+ {
+ writer.write(line.getBytes(DEFAULT_ENCODING));
+ continue;
+ }
+
+ User user = _users.get(result[0]);
+
+ if (user == null)
+ {
+ writer.write(line.getBytes(DEFAULT_ENCODING));
+ writer.println();
+ }
+ else if (!user.isDeleted())
+ {
+ if (!user.isModified())
+ {
+ writer.write(line.getBytes(DEFAULT_ENCODING));
+ writer.println();
+ }
+ else
+ {
+ try
+ {
+ byte[] encodedPassword = user.getEncodePassword();
+
+ writer.write((user.getName() + ":").getBytes(DEFAULT_ENCODING));
+ writer.write(encodedPassword);
+ writer.println();
+
+ user.saved();
+ }
+ catch (Exception e)
+ {
+ _logger.warn("Unable to encode new password reverting to old password.");
+ writer.write(line.getBytes(DEFAULT_ENCODING));
+ writer.println();
+ }
+ }
+ }
+ }
+
+ for (User user : _users.values())
+ {
+ if (user.isModified())
+ {
+ byte[] encodedPassword;
+ try
+ {
+ encodedPassword = user.getEncodePassword();
+ writer.write((user.getName() + ":").getBytes(DEFAULT_ENCODING));
+ writer.write(encodedPassword);
+ writer.println();
+ user.saved();
+ }
+ catch (Exception e)
+ {
+ _logger.warn("Unable to get Encoded password for user'" + user.getName() + "' password not saved");
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ reader.close();
+ }
+
+ if (writer != null)
+ {
+ writer.close();
+ }
+
+ // Swap temp file to main password file.
+ File old = new File(_passwordFile.getAbsoluteFile() + ".old");
+ if (old.exists())
+ {
+ old.delete();
+ }
+ _passwordFile.renameTo(old);
+ tmp.renameTo(_passwordFile);
+ tmp.delete();
+ }
+ }
+ finally
+ {
+ if (_userUpdate.isHeldByCurrentThread())
+ {
+ _userUpdate.unlock();
+ }
+ }
+ }
+
+ private class User implements Principal
+ {
+ String _name;
+ char[] _password;
+ byte[] _encodedPassword = null;
+ private boolean _modified = false;
+ private boolean _deleted = false;
+
+ User(String[] data) throws UnsupportedEncodingException
+ {
+ if (data.length != 2)
+ {
+ throw new IllegalArgumentException("User Data should be lenght 2, username, password");
+ }
+
+ _name = data[0];
+
+ byte[] encoded_password = data[1].getBytes(DEFAULT_ENCODING);
+
+ Base64 b64 = new Base64();
+ byte[] decoded = b64.decode(encoded_password);
+
+ _encodedPassword = encoded_password;
+
+ _password = new char[decoded.length];
+
+ int index = 0;
+ for (byte c : decoded)
+ {
+ _password[index++] = (char) c;
+ }
+ }
+
+ public User(String name, char[] password)
+ {
+ _name = name;
+ setPassword(password);
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String toString()
+ {
+ if (_logger.isDebugEnabled())
+ {
+ return getName() + ((_encodedPassword == null) ? "" : ":" + new String(_encodedPassword));
+ }
+ else
+ {
+ return _name;
+ }
+ }
+
+ char[] getPassword()
+ {
+ return _password;
+ }
+
+ void setPassword(char[] password)
+ {
+ _password = password;
+ _modified = true;
+ _encodedPassword = null;
+ }
+
+
+ byte[] getEncodePassword() throws EncoderException, UnsupportedEncodingException, NoSuchAlgorithmException
+ {
+ if (_encodedPassword == null)
+ {
+ encodePassword();
+ }
+ return _encodedPassword;
+ }
+
+ private void encodePassword() throws EncoderException, UnsupportedEncodingException, NoSuchAlgorithmException
+ {
+ Base64 b64 = new Base64();
+ _encodedPassword = b64.encode(new String(_password).getBytes(DEFAULT_ENCODING));
+ }
+
+ public boolean isModified()
+ {
+ return _modified;
+ }
+
+ public boolean isDeleted()
+ {
+ return _deleted;
+ }
+
+ public void delete()
+ {
+ _deleted = true;
+ }
+
+ public void saved()
+ {
+ _modified = false;
+ }
+
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
index 0c35206dd3..2d3f5e5131 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
@@ -1,38 +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
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
*
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*
*/
package org.apache.qpid.server.security.auth.database;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.configuration.PropertyUtils;
+import org.apache.qpid.configuration.PropertyException;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.configuration.PropertyUtils;
-import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
+import org.apache.qpid.server.security.access.AMQUserManagementMBean;
+import org.apache.qpid.AMQException;
-import java.util.Map;
-import java.util.List;
-import java.util.HashMap;
-import java.lang.reflect.Method;
-import java.io.FileNotFoundException;
+import javax.management.JMException;
public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatabaseManager
{
@@ -80,18 +88,21 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
initialisePrincipalDatabase((PrincipalDatabase) o, config, i);
String name = databaseNames.get(i);
- if (name == null || name.length() == 0)
+ if ((name == null) || (name.length() == 0))
{
throw new Exception("Principal database names must have length greater than or equal to one character");
}
+
PrincipalDatabase pd = databases.get(name);
if (pd != null)
{
throw new Exception("Duplicate principal database name not provided");
}
+
_logger.info("Initialised principal database '" + name + "' successfully");
databases.put(name, (PrincipalDatabase) o);
}
+
return databases;
}
@@ -104,14 +115,16 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
for (int i = 0; i < argumentNames.size(); i++)
{
String argName = argumentNames.get(i);
- if (argName == null || argName.length() == 0)
+ if ((argName == null) || (argName.length() == 0))
{
throw new ConfigurationException("Argument names must have length >= 1 character");
}
+
if (Character.isLowerCase(argName.charAt(0)))
{
argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
}
+
String methodName = "set" + argName;
Method method = null;
try
@@ -125,9 +138,10 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
if (method == null)
{
- throw new ConfigurationException("No method " + methodName + " found in class " + principalDatabase.getClass() +
- " hence unable to configure principal database. The method must be public and " +
- "have a single String argument with a void return type");
+ throw new ConfigurationException("No method " + methodName + " found in class "
+ + principalDatabase.getClass()
+ + " hence unable to configure principal database. The method must be public and "
+ + "have a single String argument with a void return type");
}
try
@@ -136,7 +150,14 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
}
catch (Exception ite)
{
- throw new ConfigurationException(ite.getCause());
+ if (ite instanceof ConfigurationException)
+ {
+ throw(ConfigurationException) ite;
+ }
+ else
+ {
+ throw new ConfigurationException(ite.getMessage(), ite);
+ }
}
}
}
@@ -145,4 +166,71 @@ public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatab
{
return _databases;
}
+
+ public void initialiseManagement(Configuration config) throws ConfigurationException
+ {
+ try
+ {
+ AMQUserManagementMBean _mbean = new AMQUserManagementMBean();
+
+ String baseSecurity = "security.jmx";
+ List<String> principalDBs = config.getList(baseSecurity + ".principal-database");
+
+ if (principalDBs.size() == 0)
+ {
+ throw new ConfigurationException("No principal-database specified for jmx security(" + baseSecurity + ".principal-database)");
+ }
+
+ String databaseName = principalDBs.get(0);
+
+ PrincipalDatabase database = getDatabases().get(databaseName);
+
+ if (database == null)
+ {
+ throw new ConfigurationException("Principal-database '" + databaseName + "' not found");
+ }
+
+ _mbean.setPrincipalDatabase(database);
+
+ List<String> jmxaccesslist = config.getList(baseSecurity + ".access");
+
+ if (jmxaccesslist.size() == 0)
+ {
+ throw new ConfigurationException("No access control files specified for jmx security(" + baseSecurity + ".access)");
+ }
+
+ String jmxaccesssFile = null;
+
+ try
+ {
+ jmxaccesssFile = PropertyUtils.replaceProperties(jmxaccesslist.get(0));
+ }
+ catch (PropertyException e)
+ {
+ throw new ConfigurationException("Unable to parse access control filename '" + jmxaccesssFile + "'");
+ }
+
+ try
+ {
+ _mbean.setAccessFile(jmxaccesssFile);
+ }
+ catch (IOException e)
+ {
+ _logger.warn("Unable to load access file:" + jmxaccesssFile);
+ }
+
+ try
+ {
+ _mbean.register();
+ }
+ catch (AMQException e)
+ {
+ _logger.warn("Unable to register user management MBean");
+ }
+ }
+ catch (JMException e)
+ {
+ _logger.warn("User management disabled as unable to create MBean:" + e);
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/MD5PasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/MD5PasswordFilePrincipalDatabase.java
deleted file mode 100644
index c24a5f21e9..0000000000
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/MD5PasswordFilePrincipalDatabase.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- *
- */
-package org.apache.qpid.server.security.auth.database;
-
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
-import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
-
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.login.AccountNotFoundException;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.regex.Pattern;
-import java.util.Map;
-import java.util.HashMap;
-import java.security.Principal;
-
-/**
- * Represents a user database where the account information is stored in a simple flat file.
- *
- * The file is expected to be in the form: username:password username1:password1 ... usernamen:passwordn
- *
- * where a carriage return separates each username/password pair. Passwords are assumed to be in plain text.
- */
-public class MD5PasswordFilePrincipalDatabase implements PrincipalDatabase
-{
- private static final Logger _logger = Logger.getLogger(MD5PasswordFilePrincipalDatabase.class);
-
- private File _passwordFile;
-
- private Pattern _regexp = Pattern.compile(":");
-
- private Map<String, AuthenticationProviderInitialiser> _saslServers;
-
- public MD5PasswordFilePrincipalDatabase()
- {
- _saslServers = new HashMap<String, AuthenticationProviderInitialiser>();
-
- /**
- * Create Authenticators for MD5 Password file.
- */
-
- // Accept MD5 incomming and use plain comparison with the file
- PlainInitialiser cram = new PlainInitialiser();
- cram.initialise(this);
- // Accept Plain incomming and hash it for comparison to the file.
- CRAMMD5Initialiser plain = new CRAMMD5Initialiser();
- plain.initialise(this,CRAMMD5Initialiser.HashDirection.INCOMMING);
-
- _saslServers.put(plain.getMechanismName(), cram);
- _saslServers.put(cram.getMechanismName(), plain);
- }
-
- public void setPasswordFile(String passwordFile) throws FileNotFoundException
- {
- File f = new File(passwordFile);
- _logger.info("PasswordFilePrincipalDatabase using file " + f.getAbsolutePath());
- _passwordFile = f;
- if (!f.exists())
- {
- throw new FileNotFoundException("Cannot find password file " + f);
- }
- if (!f.canRead())
- {
- throw new FileNotFoundException("Cannot read password file " + f +
- ". Check permissions.");
- }
- }
-
- public void setPassword(Principal principal, PasswordCallback callback) throws IOException,
- AccountNotFoundException
- {
- if (_passwordFile == null)
- {
- throw new AccountNotFoundException("Unable to locate principal since no password file was specified during initialisation");
- }
- if (principal == null)
- {
- throw new IllegalArgumentException("principal must not be null");
- }
- char[] pwd = lookupPassword(principal.getName());
- if (pwd != null)
- {
- callback.setPassword(pwd);
- }
- else
- {
- throw new AccountNotFoundException("No account found for principal " + principal);
- }
- }
-
- public Map<String, AuthenticationProviderInitialiser> getMechanisms()
- {
- return _saslServers;
- }
-
- /**
- * Looks up the password for a specified user in the password file. Note this code is <b>not</b> secure since it
- * creates strings of passwords. It should be modified to create only char arrays which get nulled out.
- *
- * @param name
- *
- * @return
- *
- * @throws java.io.IOException
- */
- private char[] lookupPassword(String name) throws IOException
- {
- BufferedReader reader = null;
- try
- {
- reader = new BufferedReader(new FileReader(_passwordFile));
- String line;
-
- while ((line = reader.readLine()) != null)
- {
- String[] result = _regexp.split(line);
- if (result == null || result.length < 2)
- {
- continue;
- }
-
- if (name.equals(result[0]))
- {
- return result[1].toCharArray();
- }
- }
- return null;
- }
- finally
- {
- if (reader != null)
- {
- reader.close();
- }
- }
- }
-}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
index 3abdd9a7ff..3f6794aaaf 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabase.java
@@ -21,8 +21,8 @@
package org.apache.qpid.server.security.auth.database;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.security.auth.sasl.amqplain.AmqPlainInitialiser;
import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
@@ -34,9 +34,11 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
+import java.io.UnsupportedEncodingException;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.HashMap;
+import java.util.List;
import java.security.Principal;
/**
@@ -119,21 +121,103 @@ public class PlainPasswordFilePrincipalDatabase implements PrincipalDatabase
}
}
+ public boolean verifyPassword(String principal, String password) throws AccountNotFoundException
+ {
+ try
+ {
+ char[] pwd = lookupPassword(principal);
+
+ return compareCharArray(pwd, convertPassword(password));
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ private char[] convertPassword(String password) throws UnsupportedEncodingException
+ {
+ byte[] passwdBytes = password.getBytes("utf-8");
+
+ char[] passwd = new char[passwdBytes.length];
+
+ int index = 0;
+
+ for (byte b : passwdBytes)
+ {
+ passwd[index++] = (char) b;
+ }
+
+ return passwd;
+ }
+
+ public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException
+ {
+ return false; // updates denied
+ }
+
+ public boolean createPrincipal(Principal principal, String password)
+ {
+ return false; // updates denied
+ }
+
+ public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
+ {
+ return false; // updates denied
+ }
+
public Map<String, AuthenticationProviderInitialiser> getMechanisms()
{
return _saslServers;
}
+ public List<Principal> getUsers()
+ {
+ return null; //todo
+ }
+
+ public Principal getUser(String username)
+ {
+ try
+ {
+ if (lookupPassword(username) != null)
+ {
+ return new UsernamePrincipal(username);
+ }
+ }
+ catch (IOException e)
+ {
+ //fall through to null return
+ }
+ return null;
+ }
+
+ private boolean compareCharArray(char[] a, char[] b)
+ {
+ boolean equal = false;
+ if (a.length == b.length)
+ {
+ equal = true;
+ int index = 0;
+ while (equal && index < a.length)
+ {
+ equal = a[index] == b[index];
+ index++;
+ }
+ }
+ return equal;
+ }
+
/**
* Looks up the password for a specified user in the password file. Note this code is <b>not</b> secure since it
* creates strings of passwords. It should be modified to create only char arrays which get nulled out.
*
- * @param name
+ * @param name the name of the principal to lookup
*
- * @return
+ * @return char[] of the password
*
- * @throws java.io.IOException
+ * @throws java.io.IOException whilst accessing the file
*/
private char[] lookupPassword(String name) throws IOException
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java
index c8318d6e64..598f8f8b4c 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PlainPasswordVhostFilePrincipalDatabase.java
@@ -20,26 +20,17 @@
*/
package org.apache.qpid.server.security.auth.database;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
-import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
-import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
import org.apache.qpid.server.security.access.AccessManager;
import org.apache.qpid.server.security.access.AccessResult;
import org.apache.qpid.server.security.access.Accessable;
+import org.apache.qpid.server.security.access.AccessRights;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.log4j.Logger;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.login.AccountNotFoundException;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
-import java.util.regex.Pattern;
-import java.util.Map;
-import java.util.HashMap;
import java.security.Principal;
/**
@@ -103,9 +94,15 @@ public class PlainPasswordVhostFilePrincipalDatabase extends PlainPasswordFilePr
public AccessResult isAuthorized(Accessable accessObject, String username)
{
+ return isAuthorized(accessObject, new UsernamePrincipal(username), AccessRights.Rights.READ);
+ }
+
+ public AccessResult isAuthorized(Accessable accessObject, Principal user, AccessRights.Rights rights)
+ {
+
if (accessObject instanceof VirtualHost)
{
- String[] hosts = lookupVirtualHost(username);
+ String[] hosts = lookupVirtualHost(user.getName());
if (hosts != null)
{
@@ -126,4 +123,5 @@ public class PlainPasswordVhostFilePrincipalDatabase extends PlainPasswordFilePr
{
return "PlainPasswordVhostFile";
}
+
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java
index 6c5a2a44ee..8073fcc3c6 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java
@@ -23,8 +23,10 @@ package org.apache.qpid.server.security.auth.database;
import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Map;
+import java.util.List;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.AccountNotFoundException;
@@ -46,5 +48,53 @@ public interface PrincipalDatabase
void setPassword(Principal principal, PasswordCallback callback)
throws IOException, AccountNotFoundException;
+ /**
+ * Used to verify that the presented Password is correct. Currently only used by Management Console
+ * @param principal The principal to authenticate
+ * @param password The password to check
+ * @return true if password is correct
+ * @throws AccountNotFoundException if the principal cannot be found
+ */
+ boolean verifyPassword(String principal, String password)
+ throws AccountNotFoundException;
+
+ /**
+ * Update(Change) the password for the given principal
+ * @param principal Who's password is to be changed
+ * @param password The new password to use
+ * @return True if change was successful
+ * @throws AccountNotFoundException If the given principal doesn't exist in the Database
+ */
+ boolean updatePassword(Principal principal, String password)
+ throws AccountNotFoundException;
+
+ /**
+ * Create a new principal in the database
+ * @param principal The principal to create
+ * @param password The password to set for the principal
+ * @return True on a successful creation
+ */
+ boolean createPrincipal(Principal principal, String password);
+
+ /**
+ * Delete a principal
+ * @param principal The principal to delete
+ * @return True on a successful creation
+ * @throws AccountNotFoundException If the given principal doesn't exist in the Database
+ */
+ boolean deletePrincipal(Principal principal)
+ throws AccountNotFoundException;
+
+ /**
+ * Get the principal from the database with the given username
+ * @param username of the principal to lookup
+ * @return The Principal object for the given username or null if not found.
+ */
+ Principal getUser(String username);
+
+
public Map<String, AuthenticationProviderInitialiser> getMechanisms();
+
+
+ List<Principal> getUsers();
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
index 83f1201bd8..2c553ae76a 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
@@ -21,10 +21,14 @@
package org.apache.qpid.server.security.auth.database;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
import java.util.Map;
public interface PrincipalDatabaseManager
{
public Map<String, PrincipalDatabase> getDatabases();
+
+ public void initialiseManagement(Configuration config) throws ConfigurationException;
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
index 9a58acd98c..b1ac0e1f00 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.security.auth.database;
import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
import org.apache.qpid.server.security.auth.sasl.crammd5.CRAMMD5Initialiser;
import org.apache.qpid.server.security.auth.sasl.plain.PlainInitialiser;
@@ -29,8 +30,10 @@ import javax.security.auth.login.AccountNotFoundException;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
+import java.util.List;
import java.security.Principal;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
public class PropertiesPrincipalDatabase implements PrincipalDatabase
{
@@ -76,8 +79,87 @@ public class PropertiesPrincipalDatabase implements PrincipalDatabase
}
}
+ public boolean verifyPassword(String principal, String password) throws AccountNotFoundException
+ {
+ char[] pwd = _users.getProperty(principal).toCharArray();
+
+ try
+ {
+ return compareCharArray(pwd, convertPassword(password));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return false;
+ }
+ }
+
+ public boolean updatePassword(Principal principal, String password) throws AccountNotFoundException
+ {
+ return false; // updates denied
+ }
+
+ public boolean createPrincipal(Principal principal, String password)
+ {
+ return false; // updates denied
+ }
+
+ public boolean deletePrincipal(Principal principal) throws AccountNotFoundException
+ {
+ return false; // updates denied
+ }
+
+ private boolean compareCharArray(char[] a, char[] b)
+ {
+ boolean equal = false;
+ if (a.length == b.length)
+ {
+ equal = true;
+ int index = 0;
+ while (equal && index < a.length)
+ {
+ equal = a[index] == b[index];
+ index++;
+ }
+ }
+ return equal;
+ }
+
+ private char[] convertPassword(String password) throws UnsupportedEncodingException
+ {
+ byte[] passwdBytes = password.getBytes("utf-8");
+
+ char[] passwd = new char[passwdBytes.length];
+
+ int index = 0;
+
+ for (byte b : passwdBytes)
+ {
+ passwd[index++] = (char) b;
+ }
+
+ return passwd;
+ }
+
+
public Map<String, AuthenticationProviderInitialiser> getMechanisms()
{
return _saslServers;
}
+
+ public List<Principal> getUsers()
+ {
+ return null; //todo
+ }
+
+ public Principal getUser(String username)
+ {
+ if (_users.getProperty(username) != null)
+ {
+ return new UsernamePrincipal(username);
+ }
+ else
+ {
+ return null;
+ }
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
index 89c84e8130..6b86a46bd2 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.security.auth.database;
+import org.apache.commons.configuration.Configuration;
+
import java.util.Map;
import java.util.Properties;
import java.util.HashMap;
@@ -38,4 +40,9 @@ public class PropertiesPrincipalDatabaseManager implements PrincipalDatabaseMana
{
return _databases;
}
+
+ public void initialiseManagement(Configuration config)
+ {
+ //todo
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index 0546bbb81e..ce5e0cd748 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -71,7 +71,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
- if (name == null)
+ if (name == null || hostConfig == null)
{
initialiseAuthenticationMechanisms(providerMap, ApplicationRegistry.getInstance().getDatabaseManager().getDatabases());
}
@@ -108,11 +108,15 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
if (providerMap.size() > 0)
{
- Security.addProvider(new JCAProvider(providerMap));
+ // Ensure we are used before the defaults
+ if (Security.insertProviderAt(new JCAProvider(providerMap), 1) == -1)
+ {
+ _logger.warn("Unable to set order of providers.");
+ }
}
else
{
- _logger.warn("No SASL providers availble.");
+ _logger.warn("No additional SASL providers registered.");
}
}
@@ -148,21 +152,20 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
if (database == null || database.getMechanisms().size() == 0)
{
- _logger.warn("");
+ _logger.warn("No Database or no mechanisms to initialise authentication");
return;
}
- for (AuthenticationProviderInitialiser mechanism : database.getMechanisms().values())
+ for (Map.Entry<String, AuthenticationProviderInitialiser> mechanism : database.getMechanisms().entrySet())
{
- initialiseAuthenticationMechanism(mechanism, providerMap);
+ initialiseAuthenticationMechanism(mechanism.getKey(), mechanism.getValue(), providerMap);
}
}
- private void initialiseAuthenticationMechanism(AuthenticationProviderInitialiser initialiser,
+ private void initialiseAuthenticationMechanism(String mechanism, AuthenticationProviderInitialiser initialiser,
Map<String, Class<? extends SaslServerFactory>> providerMap)
throws Exception
{
- String mechanism = initialiser.getMechanismName();
if (_mechanisms == null)
{
_mechanisms = mechanism;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
index 8ffcdc4e36..fd4ad86055 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
@@ -33,7 +33,7 @@ public final class JCAProvider extends Provider
super("AMQSASLProvider", 1.0, "A JCA provider that registers all " +
"AMQ SASL providers that want to be registered");
register(providerMap);
- Security.addProvider(this);
+ //Security.addProvider(this);
}
private void register(Map<String, Class<? extends SaslServerFactory>> providerMap)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java
index 68095de3a0..dd0bd096c3 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -33,14 +33,16 @@ import javax.security.auth.login.AccountNotFoundException;
import javax.security.sasl.AuthorizeCallback;
import org.apache.commons.configuration.Configuration;
+
import org.apache.log4j.Logger;
+
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser;
import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
public abstract class UsernamePasswordInitialiser implements AuthenticationProviderInitialiser
{
- protected static final Logger _logger = Logger.getLogger(UsernamePasswordInitialiser.class);
+ protected static final Logger _logger = Logger.getLogger(UsernamePasswordInitialiser.class);
private ServerCallbackHandler _callbackHandler;
@@ -72,7 +74,9 @@ public abstract class UsernamePasswordInitialiser implements AuthenticationProvi
{
// very annoyingly the callback handler does not throw anything more appropriate than
// IOException
- throw new IOException("Error looking up user " + e);
+ IOException ioe = new IOException("Error looking up user " + e);
+ ioe.initCause(e);
+ throw ioe;
}
}
else if (callback instanceof AuthorizeCallback)
@@ -88,7 +92,7 @@ public abstract class UsernamePasswordInitialiser implements AuthenticationProvi
}
public void initialise(String baseConfigPath, Configuration configuration,
- Map<String, PrincipalDatabase> principalDatabases) throws Exception
+ Map<String, PrincipalDatabase> principalDatabases) throws Exception
{
String principalDatabaseName = configuration.getString(baseConfigPath + ".principal-database");
PrincipalDatabase db = principalDatabases.get(principalDatabaseName);
@@ -102,6 +106,7 @@ public abstract class UsernamePasswordInitialiser implements AuthenticationProvi
{
throw new NullPointerException("Cannot initialise with a null Principal database.");
}
+
_callbackHandler = new ServerCallbackHandler(db);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
index f9aaabd15a..d7c8383690 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
@@ -22,10 +22,7 @@ package org.apache.qpid.server.security.auth.sasl;
import java.security.Principal;
-/**
- * A principal that is just a wrapper for a simple username.
- *
- */
+/** A principal that is just a wrapper for a simple username. */
public class UsernamePrincipal implements Principal
{
private String _name;
@@ -39,4 +36,9 @@ public class UsernamePrincipal implements Principal
{
return _name;
}
+
+ public String toString()
+ {
+ return _name;
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java
new file mode 100644
index 0000000000..97f9a4e91a
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedInitialiser.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.auth.sasl.crammd5;
+
+import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser;
+import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+
+import javax.security.sasl.SaslServerFactory;
+import java.util.Map;
+
+public class CRAMMD5HashedInitialiser extends UsernamePasswordInitialiser
+{
+ public String getMechanismName()
+ {
+ return CRAMMD5HashedSaslServer.MECHANISM;
+ }
+
+ public Class<? extends SaslServerFactory> getServerFactoryClassForJCARegistration()
+ {
+ return CRAMMD5HashedServerFactory.class;
+ }
+
+ public void initialise(PrincipalDatabase passwordFile)
+ {
+ super.initialise(passwordFile);
+ }
+
+ public Map<String, ?> getProperties()
+ {
+ return null;
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedSaslServer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedSaslServer.java
new file mode 100644
index 0000000000..f6cab084ea
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedSaslServer.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.auth.sasl.crammd5;
+
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslServerFactory;
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Enumeration;
+import java.util.Map;
+
+public class CRAMMD5HashedSaslServer implements SaslServer
+{
+ public static final String MECHANISM = "CRAM-MD5-HASHED";
+
+ private SaslServer _realServer;
+
+ public CRAMMD5HashedSaslServer(String mechanism, String protocol, String serverName, Map<String, ?> props,
+ CallbackHandler cbh) throws SaslException
+ {
+ Enumeration factories = Sasl.getSaslServerFactories();
+
+ while (factories.hasMoreElements())
+ {
+ SaslServerFactory factory = (SaslServerFactory) factories.nextElement();
+
+ if (factory instanceof CRAMMD5HashedServerFactory)
+ {
+ continue;
+ }
+
+ String[] mechs = factory.getMechanismNames(props);
+
+ for (String mech : mechs)
+ {
+ if (mech.equals("CRAM-MD5"))
+ {
+ _realServer = factory.createSaslServer("CRAM-MD5", protocol, serverName, props, cbh);
+ return;
+ }
+ }
+ }
+
+ throw new RuntimeException("No default SaslServer found for mechanism:" + "CRAM-MD5");
+ }
+
+ public String getMechanismName()
+ {
+ return MECHANISM;
+ }
+
+ public byte[] evaluateResponse(byte[] response) throws SaslException
+ {
+ return _realServer.evaluateResponse(response);
+ }
+
+ public boolean isComplete()
+ {
+ return _realServer.isComplete();
+ }
+
+ public String getAuthorizationID()
+ {
+ return _realServer.getAuthorizationID();
+ }
+
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ return _realServer.unwrap(incoming, offset, len);
+ }
+
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ return _realServer.wrap(outgoing, offset, len);
+ }
+
+ public Object getNegotiatedProperty(String propName)
+ {
+ return _realServer.getNegotiatedProperty(propName);
+ }
+
+ public void dispose() throws SaslException
+ {
+ _realServer.dispose();
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedServerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedServerFactory.java
new file mode 100644
index 0000000000..5298b5cc63
--- /dev/null
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HashedServerFactory.java
@@ -0,0 +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.server.security.auth.sasl.crammd5;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslServerFactory;
+
+public class CRAMMD5HashedServerFactory implements SaslServerFactory
+{
+ public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map<String, ?> props,
+ CallbackHandler cbh) throws SaslException
+ {
+ if (mechanism.equals(CRAMMD5HashedSaslServer.MECHANISM))
+ {
+ return new CRAMMD5HashedSaslServer(mechanism, protocol, serverName, props, cbh);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public String[] getMechanismNames(Map props)
+ {
+ if (props != null)
+ {
+ if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE))
+ {
+ // returned array must be non null according to interface documentation
+ return new String[0];
+ }
+ }
+
+ return new String[]{CRAMMD5HashedSaslServer.MECHANISM};
+ }
+}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
index ff3e87e3a0..f0dd9eeb6d 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
@@ -29,7 +29,7 @@ import javax.security.sasl.SaslServer;
import javax.security.sasl.SaslServerFactory;
public class PlainSaslServerFactory implements SaslServerFactory
-{
+{
public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map props,
CallbackHandler cbh) throws SaslException
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java
index 05d1cd5291..609a85c22f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/CleanupMessageOperation.java
@@ -56,18 +56,7 @@ public class CleanupMessageOperation implements TxnOp
public void commit(StoreContext context)
{
- //The routers reference can now be released. This is done
- //here to ensure that it happens after the queues that
- //enqueue it have incremented their counts (which as a
- //memory only operation is done in the commit phase).
- try
- {
- _msg.decrementReference(context);
- }
- catch (AMQException e)
- {
- _log.error("On commiting transaction, failed to cleanup unused message: " + e, e);
- }
+
try
{
_msg.checkDeliveredToConsumer();
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
index cf0da55f2a..6d776eec0f 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransactionalContext.java
@@ -89,6 +89,12 @@ public class LocalTransactionalContext implements TransactionalContext
public void rollback() throws AMQException
{
_txnBuffer.rollback(_storeContext);
+ // Hack to deal with uncommitted non-transactional writes
+ if(_messageStore.inTran(_storeContext))
+ {
+ _messageStore.abortTran(_storeContext);
+ _inTran = false;
+ }
_postCommitDeliveryList.clear();
}
@@ -103,6 +109,7 @@ public class LocalTransactionalContext implements TransactionalContext
// message.incrementReference();
_postCommitDeliveryList.add(new DeliveryDetails(message, queue, deliverFirst));
_messageDelivered = true;
+ _txnBuffer.enlist(new CleanupMessageOperation(message, _returnMessages));
/*_txnBuffer.enlist(new DeliverMessageOperation(message, queue));
if (_log.isDebugEnabled())
{
@@ -111,7 +118,7 @@ public class LocalTransactionalContext implements TransactionalContext
}
message.incrementReference();
_messageDelivered = true;
- _txnBuffer.enlist(new CleanupMessageOperation(message, _returnMessages));
+
*/
}
@@ -195,6 +202,7 @@ public class LocalTransactionalContext implements TransactionalContext
{
_txnBuffer.enlist(new StoreMessageOperation(_messageStore));
}
+ //fixme fail commit here ... QPID-440
try
{
_txnBuffer.commit(_storeContext);
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java
index 339ca8ae1a..405c233552 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/TxnBuffer.java
@@ -41,7 +41,7 @@ public class TxnBuffer
{
if (_log.isDebugEnabled())
{
- _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops.toArray());
+ _log.debug("Committing " + _ops.size() + " ops to commit.:" + _ops);
}
if (prepare(context))
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
index c24d1aa23a..b5c59dbbb7 100644
--- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
+++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java
@@ -181,7 +181,7 @@ public class VirtualHost implements Accessable
catch (Exception e)
{
_logger.error("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor");
- throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor");
+ throw new IllegalArgumentException("Unable to instantiate configuration class " + instanceType + " - ensure it has a public default constructor", e);
}
Configurator.configure(instance);
diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
index 236291968f..0c1da5c278 100644
--- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
+++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java
@@ -106,6 +106,8 @@ public class AMQQueueAlertTest extends TestCase
/**
* Tests if Queue Depth alert is thrown when queue depth reaches the threshold value
*
+ * Based on FT402 subbmitted by client
+ *
* @throws Exception
*/
public void testQueueDepthAlertNoSubscriber() throws Exception
diff --git a/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java b/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java
index b199d41432..6a7626c51d 100644
--- a/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java
+++ b/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageDispatcher.java
@@ -1,4 +1,5 @@
/*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -6,33 +7,35 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
+ *
*/
package org.apache.qpid.example.publisher;
-import org.apache.log4j.Logger;
-
import java.io.File;
+import javax.jms.JMSException;
+
+import org.apache.log4j.Logger;
+
import org.apache.qpid.example.shared.FileUtils;
import org.apache.qpid.example.shared.Statics;
-import javax.jms.JMSException;
-
/**
* Class that sends message files to the Publisher to distribute
* using files as input
* Must set properties for host in properties file or uses in vm broker
*/
-public class FileMessageDispatcher {
+public class FileMessageDispatcher
+{
protected static final Logger _logger = Logger.getLogger(FileMessageDispatcher.class);
@@ -48,30 +51,30 @@ public class FileMessageDispatcher {
public static void main(String[] args)
{
- //Check command line args ok - must provide a path or file for us to dispatch
+ // Check command line args ok - must provide a path or file for us to dispatch
if (args.length == 0)
{
- System.err.println("Usage: FileMessageDispatcher <filesToDispatch>" + "");
+ System.out.println("Usage: FileMessageDispatcher <filesToDispatch>" + "");
}
else
{
try
{
- //publish message(s) from file(s) to configured queue
+ // publish message(s) from file(s) to configured queue
publish(args[0]);
- //Move payload file(s) to archive location as no error
+ // Move payload file(s) to archive location as no error
FileUtils.moveFileToNewDir(args[0], System.getProperties().getProperty(Statics.ARCHIVE_PATH));
}
- catch(Exception e)
+ catch (Exception e)
{
- //log error and exit
+ // log error and exit
_logger.error("Error trying to dispatch message: " + e);
System.exit(1);
}
finally
{
- //clean up before exiting
+ // clean up before exiting
if (getPublisher() != null)
{
getPublisher().cleanup();
@@ -98,10 +101,10 @@ public class FileMessageDispatcher {
File tempFile = new File(path);
if (tempFile.isDirectory())
{
- //while more files in dir publish them
+ // while more files in dir publish them
File[] files = tempFile.listFiles();
- if (files == null || files.length == 0)
+ if ((files == null) || (files.length == 0))
{
_logger.info("FileMessageDispatcher - No files to publish in input directory: " + tempFile);
}
@@ -109,10 +112,10 @@ public class FileMessageDispatcher {
{
for (File file : files)
{
- //Create message factory passing in payload path
+ // Create message factory passing in payload path
FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(), file.toString());
- //Send the message generated from the payload using the _publisher
+ // Send the message generated from the payload using the _publisher
getPublisher().sendMessage(factory.createEventMessage());
}
@@ -120,11 +123,11 @@ public class FileMessageDispatcher {
}
else
{
- //handle a single file
- //Create message factory passing in payload path
- FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(),tempFile.toString());
+ // handle a single file
+ // Create message factory passing in payload path
+ FileMessageFactory factory = new FileMessageFactory(getPublisher().getSession(), tempFile.toString());
- //Send the message generated from the payload using the _publisher
+ // Send the message generated from the payload using the _publisher
getPublisher().sendMessage(factory.createEventMessage());
}
}
@@ -145,15 +148,15 @@ public class FileMessageDispatcher {
*/
private static Publisher getPublisher()
{
- if (_publisher != null)
- {
- return _publisher;
- }
+ if (_publisher != null)
+ {
+ return _publisher;
+ }
- //Create a _publisher
- _publisher = new Publisher();
+ // Create a _publisher
+ _publisher = new Publisher();
- return _publisher;
+ return _publisher;
}
}
diff --git a/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java b/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java
index 88bcbbbccb..f3b21e3c64 100644
--- a/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java
+++ b/qpid/java/client/example/src/main/java/org/apache/qpid/example/publisher/FileMessageFactory.java
@@ -47,7 +47,9 @@ public class FileMessageFactory
}
catch (IOException e)
{
- throw new MessageFactoryException(e.toString());
+ MessageFactoryException mfe = new MessageFactoryException(e.toString());
+ mfe.initCause(e);
+ throw mfe;
}
}
diff --git a/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java b/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java
index 8505d1d457..98a2c0d497 100644
--- a/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java
+++ b/qpid/java/client/example/src/main/java/org/apache/qpid/example/shared/InitialContextHelper.java
@@ -59,11 +59,11 @@ public class InitialContextHelper
}
catch (IOException e)
{
- throw new ContextException(e.toString());
+ throw new ContextException(e.toString(), e);
}
catch (NamingException n)
{
- throw new ContextException(n.toString());
+ throw new ContextException(n.toString(), n);
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
index 413524b6d8..0e3d99eeba 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,6 +20,29 @@
*/
package org.apache.qpid.client;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.nio.channels.UnresolvedAddressException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.jms.*;
+import javax.jms.IllegalStateException;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+
+import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQConnectionFailureException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUndeliveredException;
@@ -44,28 +67,6 @@ import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.FailoverPolicy;
import org.apache.qpid.url.URLSyntaxException;
-import org.apache.log4j.Logger;
-
-import javax.jms.*;
-import javax.jms.IllegalStateException;
-import javax.naming.NamingException;
-import javax.naming.Reference;
-import javax.naming.Referenceable;
-import javax.naming.StringRefAddr;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.nio.channels.UnresolvedAddressException;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
public class AMQConnection extends Closeable implements Connection, QueueConnection, TopicConnection, Referenceable
{
private static final Logger _logger = Logger.getLogger(AMQConnection.class);
@@ -95,7 +96,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private AMQProtocolHandler _protocolHandler;
/** Maps from session id (Integer) to AMQSession instance */
- private final Map _sessions = new LinkedHashMap(); //fixme this is map is replicated in amqprotocolsession as _channelId2SessionMap
+ private final Map _sessions = new LinkedHashMap(); // fixme this is map is replicated in amqprotocolsession as _channelId2SessionMap
private String _clientName;
@@ -125,15 +126,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/*
* _Connected should be refactored with a suitable wait object.
- */
+ */
private boolean _connected;
/*
* The last error code that occured on the connection. Used to return the correct exception to the client
- */
+ */
private AMQException _lastAMQException = null;
-
/*
* The connection meta data
*/
@@ -149,6 +149,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
/** Thread Pool for executing connection level processes. Such as returning bounced messages. */
private final ExecutorService _taskPool = Executors.newCachedThreadPool();
+ private static final long DEFAULT_TIMEOUT = 1000 * 30;
/**
* @param broker brokerdetails
@@ -160,13 +161,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
* @throws AMQException
* @throws URLSyntaxException
*/
- public AMQConnection(String broker, String username, String password,
- String clientName, String virtualHost) throws AMQException, URLSyntaxException
+ public AMQConnection(String broker, String username, String password, String clientName, String virtualHost)
+ throws AMQException, URLSyntaxException
{
- this(new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL + "://" +
- username + ":" + password + "@" +
- (clientName == null ? "" : clientName) + "/" +
- virtualHost + "?brokerlist='" + AMQBrokerDetails.checkTransport(broker) + "'"), null);
+ this(new AMQConnectionURL(
+ ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + "/" + virtualHost + "?brokerlist='"
+ + AMQBrokerDetails.checkTransport(broker) + "'"), null);
}
/**
@@ -179,44 +180,38 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
* @throws AMQException
* @throws URLSyntaxException
*/
- public AMQConnection(String broker, String username, String password,
- String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ public AMQConnection(String broker, String username, String password, String clientName, String virtualHost,
+ SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
{
- this(new AMQConnectionURL(ConnectionURL.AMQ_PROTOCOL + "://" +
- username + ":" + password + "@" +
- (clientName == null ? "" : clientName) + "/" +
- virtualHost + "?brokerlist='" + AMQBrokerDetails.checkTransport(broker) + "'"), sslConfig);
+ this(new AMQConnectionURL(
+ ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + "/" + virtualHost + "?brokerlist='"
+ + AMQBrokerDetails.checkTransport(broker) + "'"), sslConfig);
}
-
- public AMQConnection(String host, int port, String username, String password,
- String clientName, String virtualHost) throws AMQException, URLSyntaxException
+ public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost)
+ throws AMQException, URLSyntaxException
{
this(host, port, false, username, password, clientName, virtualHost, null);
}
- public AMQConnection(String host, int port, String username, String password,
- String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost,
+ SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
{
this(host, port, false, username, password, clientName, virtualHost, sslConfig);
}
-
- public AMQConnection(String host, int port, boolean useSSL, String username, String password,
- String clientName, String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
+ public AMQConnection(String host, int port, boolean useSSL, String username, String password, String clientName,
+ String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException
{
- this(new AMQConnectionURL(useSSL ?
- ConnectionURL.AMQ_PROTOCOL + "://" +
- username + ":" + password + "@" +
- (clientName == null ? "" : clientName) +
- virtualHost + "?brokerlist='tcp://" + host + ":" + port + "'"
- + "," + ConnectionURL.OPTIONS_SSL + "='true'" :
- ConnectionURL.AMQ_PROTOCOL + "://" +
- username + ":" + password + "@" +
- (clientName == null ? "" : clientName) +
- virtualHost + "?brokerlist='tcp://" + host + ":" + port + "'"
- + "," + ConnectionURL.OPTIONS_SSL + "='false'"
- ), sslConfig);
+ this(new AMQConnectionURL(
+ useSSL
+ ? (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port
+ + "'" + "," + ConnectionURL.OPTIONS_SSL + "='true'")
+ : (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
+ + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port
+ + "'" + "," + ConnectionURL.OPTIONS_SSL + "='false'")), sslConfig);
}
public AMQConnection(String connection) throws AMQException, URLSyntaxException
@@ -229,13 +224,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
this(new AMQConnectionURL(connection), sslConfig);
}
-
public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException
{
if (_logger.isInfoEnabled())
{
_logger.info("Connection:" + connectionURL);
}
+
_sslConfiguration = sslConfig;
if (connectionURL == null)
{
@@ -249,7 +244,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_password = connectionURL.getPassword();
setVirtualHost(connectionURL.getVirtualHost());
-
if (connectionURL.getDefaultQueueExchangeName() != null)
{
_defaultQueueExchangeName = connectionURL.getDefaultQueueExchangeName();
@@ -270,7 +264,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_temporaryTopicExchangeName = connectionURL.getTemporaryTopicExchangeName();
}
-
_failoverPolicy = new FailoverPolicy(connectionURL);
_protocolHandler = new AMQProtocolHandler(this);
@@ -278,7 +271,6 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
// We are not currently connected
_connected = false;
-
Exception lastException = new Exception();
lastException.initCause(new ConnectException());
@@ -296,7 +288,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
if (_logger.isInfoEnabled())
{
- _logger.info("Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails(), e.getCause());
+ _logger.info("Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails(),
+ e.getCause());
}
}
}
@@ -322,7 +315,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
- if (message == null || message.equals(""))
+ if ((message == null) || message.equals(""))
{
message = "Unable to Connect";
}
@@ -335,11 +328,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
e = new AMQUnresolvedAddressException(message, _failoverPolicy.getCurrentBrokerDetails().toString());
}
+
e.initCause(lastException);
}
throw e;
}
+
_connectionMetaData = new QpidConnectionMetaData(this);
}
@@ -369,6 +364,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
virtualHost = virtualHost.substring(1);
}
+
_virtualHost = virtualHost;
}
@@ -382,7 +378,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
_protocolHandler.attainState(AMQState.CONNECTION_OPEN);
_failoverPolicy.attainedConnection();
- //Again this should be changed to a suitable notify
+ // Again this should be changed to a suitable notify
_connected = true;
}
catch (AMQException e)
@@ -401,6 +397,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
try
{
makeBrokerConnection(bd);
+
return true;
}
catch (Exception e)
@@ -409,8 +406,10 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_logger.info("Unable to connect to broker at " + bd);
}
+
attemptReconnection();
}
+
return false;
}
@@ -421,6 +420,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
try
{
makeBrokerConnection(_failoverPolicy.getNextBrokerDetails());
+
return true;
}
catch (Exception e)
@@ -436,13 +436,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
if (_logger.isInfoEnabled())
{
- _logger.info(e.getMessage() + ":Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails());
+ _logger.info(e.getMessage() + ":Unable to connect to broker at "
+ + _failoverPolicy.getCurrentBrokerDetails());
}
}
}
}
- //connection unsuccessful
+ // connection unsuccessful
return false;
}
@@ -474,14 +475,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return createSession(transacted, acknowledgeMode, AMQSession.DEFAULT_PREFETCH_HIGH_MARK);
}
- public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode,
- final int prefetch) throws JMSException
+ public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode, final int prefetch)
+ throws JMSException
{
return createSession(transacted, acknowledgeMode, prefetch, prefetch);
}
public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode,
- final int prefetchHigh, final int prefetchLow) throws JMSException
+ final int prefetchHigh, final int prefetchLow) throws JMSException
{
checkNotClosed();
if (channelLimitReached())
@@ -491,85 +492,81 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
else
{
return (org.apache.qpid.jms.Session) new FailoverSupport()
- {
- public Object operation() throws JMSException
- {
- int channelId = _idFactory.incrementAndGet();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Write channel open frame for channel id " + channelId);
- }
-
- // We must create the session and register it before actually sending the frame to the server to
- // open it, so that there is no window where we could receive data on the channel and not be set
- // up to handle it appropriately.
- AMQSession session = new AMQSession(AMQConnection.this, channelId, transacted, acknowledgeMode,
- prefetchHigh, prefetchLow);
- _protocolHandler.addSessionByChannel(channelId, session);
- registerSession(channelId, session);
-
- boolean success = false;
- try
- {
- createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted);
- success = true;
- }
- catch (AMQException e)
- {
- JMSException jmse = new JMSException("Error creating session: " + e);
- jmse.setLinkedException(e);
- throw jmse;
- }
- finally
- {
- if (!success)
- {
- _protocolHandler.removeSessionByChannel(channelId);
- deregisterSession(channelId);
- }
- }
-
- if (_started)
{
- try
- {
- session.start();
- }
- catch (AMQException e)
+ public Object operation() throws JMSException
{
- throw new JMSAMQException(e);
+ int channelId = _idFactory.incrementAndGet();
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Write channel open frame for channel id " + channelId);
+ }
+
+ // We must create the session and register it before actually sending the frame to the server to
+ // open it, so that there is no window where we could receive data on the channel and not be set
+ // up to handle it appropriately.
+ AMQSession session =
+ new AMQSession(AMQConnection.this, channelId, transacted, acknowledgeMode, prefetchHigh,
+ prefetchLow);
+ _protocolHandler.addSessionByChannel(channelId, session);
+ registerSession(channelId, session);
+
+ boolean success = false;
+ try
+ {
+ createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted);
+ success = true;
+ }
+ catch (AMQException e)
+ {
+ JMSException jmse = new JMSException("Error creating session: " + e);
+ jmse.setLinkedException(e);
+ throw jmse;
+ }
+ finally
+ {
+ if (!success)
+ {
+ _protocolHandler.removeSessionByChannel(channelId);
+ deregisterSession(channelId);
+ }
+ }
+
+ if (_started)
+ {
+ try
+ {
+ session.start();
+ }
+ catch (AMQException e)
+ {
+ throw new JMSAMQException(e);
+ }
+ }
+
+ return session;
}
- }
- return session;
- }
- }.execute(this);
+ }.execute(this);
}
}
private void createChannelOverWire(int channelId, int prefetchHigh, int prefetchLow, boolean transacted)
- throws AMQException
+ throws AMQException
{
// TODO: Be aware of possible changes to parameter order as versions change.
- _protocolHandler.syncWrite(
- ChannelOpenBody.createAMQFrame(channelId,
- _protocolHandler.getProtocolMajorVersion(),
- _protocolHandler.getProtocolMinorVersion(),
- null), // outOfBand
- ChannelOpenOkBody.class);
-
- //todo send low water mark when protocol allows.
- //todo Be aware of possible changes to parameter order as versions change.
- _protocolHandler.syncWrite(
- BasicQosBody.createAMQFrame(channelId,
- _protocolHandler.getProtocolMajorVersion(),
- _protocolHandler.getProtocolMinorVersion(),
- false, // global
- prefetchHigh, // prefetchCount
- 0), // prefetchSize
- BasicQosOkBody.class);
+ _protocolHandler.syncWrite(ChannelOpenBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(),
+ _protocolHandler.getProtocolMinorVersion(), null), // outOfBand
+ ChannelOpenOkBody.class);
+
+ // todo send low water mark when protocol allows.
+ // todo Be aware of possible changes to parameter order as versions change.
+ _protocolHandler.syncWrite(BasicQosBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(),
+ _protocolHandler.getProtocolMinorVersion(), false, // global
+ prefetchHigh, // prefetchCount
+ 0), // prefetchSize
+ BasicQosOkBody.class);
if (transacted)
{
@@ -579,10 +576,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
// TODO: Be aware of possible changes to parameter order as versions change.
- _protocolHandler.syncWrite(TxSelectBody.createAMQFrame(channelId,
- _protocolHandler.getProtocolMajorVersion(),
- _protocolHandler.getProtocolMinorVersion()),
- TxSelectOkBody.class);
+ _protocolHandler.syncWrite(TxSelectBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(),
+ _protocolHandler.getProtocolMinorVersion()), TxSelectOkBody.class);
}
}
@@ -596,11 +591,10 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_protocolHandler.removeSessionByChannel(channelId);
deregisterSession(channelId);
- throw new AMQException("Error reopening channel " + channelId + " after failover: " + e);
+ throw new AMQException("Error reopening channel " + channelId + " after failover: " + e, e);
}
}
-
public void setFailoverPolicy(FailoverPolicy policy)
{
_failoverPolicy = policy;
@@ -645,12 +639,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
private boolean channelLimitReached()
{
- return _maximumChannelCount != 0 && _sessions.size() == _maximumChannelCount;
+ return (_maximumChannelCount != 0) && (_sessions.size() == _maximumChannelCount);
}
public String getClientID() throws JMSException
{
checkNotClosed();
+
return _clientName;
}
@@ -666,6 +661,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public ConnectionMetaData getMetaData() throws JMSException
{
checkNotClosed();
+
return _connectionMetaData;
}
@@ -673,6 +669,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public ExceptionListener getExceptionListener() throws JMSException
{
checkNotClosed();
+
return _exceptionListener;
}
@@ -706,6 +703,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
throw new JMSAMQException(e);
}
}
+
_started = true;
}
}
@@ -726,13 +724,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
throw new JMSAMQException(e);
}
}
+
_started = false;
}
}
public void close() throws JMSException
{
- close(-1);
+ close(DEFAULT_TIMEOUT);
}
public void close(long timeout) throws JMSException
@@ -752,7 +751,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
try
{
- //adjust timeout
+ // adjust timeout
long taskPoolTimeout = adjustTimeout(timeout, startCloseTime);
_taskPool.awaitTermination(taskPoolTimeout, TimeUnit.MILLISECONDS);
@@ -763,7 +762,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
- //adjust timeout
+ // adjust timeout
timeout = adjustTimeout(timeout, startCloseTime);
_protocolHandler.closeConnection(timeout);
@@ -771,7 +770,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
catch (AMQException e)
{
- throw new JMSException("Error closing connection: " + e);
+ JMSException jmse = new JMSException("Error closing connection: " + e);
+ jmse.setLinkedException(e);
+ throw jmse;
}
}
}
@@ -785,6 +786,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
timeout = 0;
}
+
return timeout;
}
@@ -803,6 +805,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
session.markClosed();
}
+
_sessions.clear();
}
@@ -842,6 +845,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
}
}
+
_sessions.clear();
if (sessionException != null)
{
@@ -850,42 +854,42 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
}
public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector,
- ServerSessionPool sessionPool,
- int maxMessages) throws JMSException
+ ServerSessionPool sessionPool, int maxMessages) throws JMSException
{
checkNotClosed();
+
return null;
}
- public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector,
- ServerSessionPool sessionPool,
- int maxMessages) throws JMSException
+ public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector, ServerSessionPool sessionPool,
+ int maxMessages) throws JMSException
{
checkNotClosed();
+
return null;
}
- public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector,
- ServerSessionPool sessionPool,
- int maxMessages) throws JMSException
+ public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector, ServerSessionPool sessionPool,
+ int maxMessages) throws JMSException
{
checkNotClosed();
+
return null;
}
- public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName,
- String messageSelector, ServerSessionPool sessionPool,
- int maxMessages)
- throws JMSException
+ public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector,
+ ServerSessionPool sessionPool, int maxMessages) throws JMSException
{
// TODO Auto-generated method stub
checkNotClosed();
+
return null;
}
public long getMaximumChannelCount() throws JMSException
{
checkNotClosed();
+
return _maximumChannelCount;
}
@@ -974,6 +978,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
proceed = _connectionListener.preFailover(redirect);
}
+
return proceed;
}
@@ -994,6 +999,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
markAllSessionsClosed();
}
+
return resubscribe;
}
else
@@ -1057,12 +1063,15 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
if (cause instanceof AMQException)
{
- je = new JMSException(Integer.toString(((AMQException) cause).getErrorCode().getCode()), "Exception thrown against " + toString() + ": " + cause);
+ je =
+ new JMSException(Integer.toString(((AMQException) cause).getErrorCode().getCode()),
+ "Exception thrown against " + toString() + ": " + cause);
}
else
{
je = new JMSException("Exception thrown against " + toString() + ": " + cause);
}
+
if (cause instanceof Exception)
{
je.setLinkedException((Exception) cause);
@@ -1090,6 +1099,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
{
_logger.info("Closing AMQConnection due to :" + cause.getMessage());
}
+
_closed.set(true);
closeAllSessions(cause, -1, -1); // FIXME: when doing this end up with RejectedExecutionException from executor.
}
@@ -1145,9 +1155,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
buf.append("Host: ").append(String.valueOf(bd.getHost()));
buf.append("\nPort: ").append(String.valueOf(bd.getPort()));
}
+
buf.append("\nVirtual Host: ").append(String.valueOf(_virtualHost));
buf.append("\nClient ID: ").append(String.valueOf(_clientName));
- buf.append("\nActive session count: ").append(_sessions == null ? 0 : _sessions.size());
+ buf.append("\nActive session count: ").append((_sessions == null) ? 0 : _sessions.size());
+
return buf.toString();
}
@@ -1158,11 +1170,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public Reference getReference() throws NamingException
{
- return new Reference(
- AMQConnection.class.getName(),
- new StringRefAddr(AMQConnection.class.getName(), toURL()),
- AMQConnectionFactory.class.getName(),
- null); // factory location
+ return new Reference(AMQConnection.class.getName(), new StringRefAddr(AMQConnection.class.getName(), toURL()),
+ AMQConnectionFactory.class.getName(), null); // factory location
}
public SSLConfiguration getSSLConfiguration()
@@ -1175,19 +1184,16 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
return _defaultTopicExchangeName;
}
-
public void setDefaultTopicExchangeName(AMQShortString defaultTopicExchangeName)
{
_defaultTopicExchangeName = defaultTopicExchangeName;
}
-
public AMQShortString getDefaultQueueExchangeName()
{
return _defaultQueueExchangeName;
}
-
public void setDefaultQueueExchangeName(AMQShortString defaultQueueExchangeName)
{
_defaultQueueExchangeName = defaultQueueExchangeName;
@@ -1200,10 +1206,9 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect
public AMQShortString getTemporaryQueueExchangeName()
{
- return _temporaryQueueExchangeName; //To change body of created methods use File | Settings | File Templates.
+ return _temporaryQueueExchangeName; // To change body of created methods use File | Settings | File Templates.
}
-
public void setTemporaryTopicExchangeName(AMQShortString temporaryTopicExchangeName)
{
_temporaryTopicExchangeName = temporaryTopicExchangeName;
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
index 0dcc544ea8..b3fbd1f510 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,12 +20,6 @@
*/
package org.apache.qpid.client;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.jms.BrokerDetails;
-import org.apache.qpid.jms.ConnectionURL;
-import org.apache.qpid.url.URLHelper;
-import org.apache.qpid.url.URLSyntaxException;
-
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
@@ -33,6 +27,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.jms.BrokerDetails;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.url.URLHelper;
+import org.apache.qpid.url.URLSyntaxException;
+
public class AMQConnectionURL implements ConnectionURL
{
private String _url;
@@ -49,7 +49,6 @@ public class AMQConnectionURL implements ConnectionURL
private AMQShortString _temporaryTopicExchangeName;
private AMQShortString _temporaryQueueExchangeName;
-
public AMQConnectionURL(String fullURL) throws URLSyntaxException
{
_url = fullURL;
@@ -58,18 +57,18 @@ public class AMQConnectionURL implements ConnectionURL
_failoverOptions = new HashMap<String, String>();
// Connection URL format
- //amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''"
+ // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''"
// Options are of course optional except for requiring a single broker in the broker list.
try
{
URI connection = new URI(fullURL);
- if (connection.getScheme() == null || !(connection.getScheme().equalsIgnoreCase(AMQ_PROTOCOL)))
+ if ((connection.getScheme() == null) || !(connection.getScheme().equalsIgnoreCase(AMQ_PROTOCOL)))
{
throw new URISyntaxException(fullURL, "Not an AMQP URL");
}
- if (connection.getHost() == null || connection.getHost().equals(""))
+ if ((connection.getHost() == null) || connection.getHost().equals(""))
{
String uid = AMQConnectionFactory.getUniqueClientID();
if (uid == null)
@@ -91,7 +90,7 @@ public class AMQConnectionURL implements ConnectionURL
if (userInfo == null)
{
- //Fix for Java 1.5 which doesn't parse UserInfo for non http URIs
+ // Fix for Java 1.5 which doesn't parse UserInfo for non http URIs
userInfo = connection.getAuthority();
if (userInfo != null)
@@ -112,16 +111,16 @@ public class AMQConnectionURL implements ConnectionURL
if (userInfo == null)
{
- throw URLHelper.parseError(AMQ_PROTOCOL.length() + 3,
- "User information not found on url", fullURL);
+ throw URLHelper.parseError(AMQ_PROTOCOL.length() + 3, "User information not found on url", fullURL);
}
else
{
parseUserInfo(userInfo);
}
+
String virtualHost = connection.getPath();
- if (virtualHost != null && (!virtualHost.equals("")))
+ if ((virtualHost != null) && (!virtualHost.equals("")))
{
setVirtualHost(virtualHost);
}
@@ -130,7 +129,7 @@ public class AMQConnectionURL implements ConnectionURL
int authLength = connection.getAuthority().length();
int start = AMQ_PROTOCOL.length() + 3;
int testIndex = start + authLength;
- if (testIndex < fullURL.length() && fullURL.charAt(testIndex) == '?')
+ if ((testIndex < fullURL.length()) && (fullURL.charAt(testIndex) == '?'))
{
throw URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL);
}
@@ -141,14 +140,9 @@ public class AMQConnectionURL implements ConnectionURL
}
-
URLHelper.parseOptions(_options, connection.getQuery());
processOptions();
-
- //Fragment is #string (not used)
- //System.out.println(connection.getFragment());
-
}
catch (URISyntaxException uris)
{
@@ -165,11 +159,10 @@ public class AMQConnectionURL implements ConnectionURL
}
else
{
- if (slash != 0 && fullURL.charAt(slash - 1) == ':')
+ if ((slash != 0) && (fullURL.charAt(slash - 1) == ':'))
{
throw URLHelper.parseError(slash - 2, fullURL.indexOf('?') - slash + 2,
- "Virtual host looks like a windows path, forward slash not allowed in URL",
- fullURL);
+ "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL);
}
else
{
@@ -182,14 +175,14 @@ public class AMQConnectionURL implements ConnectionURL
private void parseUserInfo(String userinfo) throws URLSyntaxException
{
- //user info = user:pass
+ // user info = user:pass
int colonIndex = userinfo.indexOf(':');
if (colonIndex == -1)
{
throw URLHelper.parseError(AMQ_PROTOCOL.length() + 3, userinfo.length(),
- "Null password in user information not allowed.", _url);
+ "Null password in user information not allowed.", _url);
}
else
{
@@ -205,7 +198,7 @@ public class AMQConnectionURL implements ConnectionURL
{
String brokerlist = _options.get(OPTIONS_BROKERLIST);
- //brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'
+ // brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'
StringTokenizer st = new StringTokenizer(brokerlist, "" + URLHelper.BROKER_SEPARATOR);
while (st.hasMoreTokens())
@@ -244,19 +237,16 @@ public class AMQConnectionURL implements ConnectionURL
_defaultTopicExchangeName = new AMQShortString(_options.get(OPTIONS_DEFAULT_TOPIC_EXCHANGE));
}
-
if (_options.containsKey(OPTIONS_DEFAULT_QUEUE_EXCHANGE))
{
_defaultQueueExchangeName = new AMQShortString(_options.get(OPTIONS_DEFAULT_QUEUE_EXCHANGE));
}
-
if (_options.containsKey(OPTIONS_TEMPORARY_QUEUE_EXCHANGE))
{
_temporaryQueueExchangeName = new AMQShortString(_options.get(OPTIONS_TEMPORARY_QUEUE_EXCHANGE));
}
-
if (_options.containsKey(OPTIONS_TEMPORARY_TOPIC_EXCHANGE))
{
_temporaryTopicExchangeName = new AMQShortString(_options.get(OPTIONS_TEMPORARY_TOPIC_EXCHANGE));
@@ -439,12 +429,11 @@ public class AMQConnectionURL implements ConnectionURL
return sb.toString();
}
-
public static void main(String[] args) throws URLSyntaxException
{
-
- String url2 = "amqp://ritchiem:bob@temp?brokerlist='tcp://localhost:5672;jcp://fancyserver:3000/',failover='roundrobin'";
- //"amqp://user:pass@clientid/virtualhost?brokerlist='tcp://host:1?option1=\'value\',option2=\'value\';vm://:3?option1=\'value\'',failover='method?option1=\'value\',option2='value''";
+ String url2 =
+ "amqp://ritchiem:bob@temp?brokerlist='tcp://localhost:5672;jcp://fancyserver:3000/',failover='roundrobin'";
+ // "amqp://user:pass@clientid/virtualhost?brokerlist='tcp://host:1?option1=\'value\',option2=\'value\';vm://:3?option1=\'value\'',failover='method?option1=\'value\',option2='value''";
ConnectionURL connectionurl2 = new AMQConnectionURL(url2);
@@ -452,5 +441,4 @@ public class AMQConnectionURL implements ConnectionURL
System.out.println(connectionurl2);
}
-
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
index 661372845a..585991d905 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
@@ -53,6 +53,8 @@ public abstract class AMQDestination implements Destination, Referenceable
private String _url;
private AMQShortString _urlAsShortString;
+ private boolean _validated;
+
private byte[] _byteEncoding;
private static final int IS_DURABLE_MASK = 0x1;
private static final int IS_EXCLUSIVE_MASK = 0x2;
@@ -198,12 +200,16 @@ public abstract class AMQDestination implements Destination, Referenceable
{
return toURL();
- /*
- return "Destination: " + _destinationName + ", " +
- "Queue Name: " + _queueName + ", Exchange: " + _exchangeName +
- ", Exchange class: " + _exchangeClass + ", Exclusive: " + _isExclusive +
- ", AutoDelete: " + _isAutoDelete + ", Routing Key: " + getRoutingKey();
- */
+ }
+
+ public boolean isValidated()
+ {
+ return _validated;
+ }
+
+ public void setValidated(boolean validated)
+ {
+ _validated = validated;
}
public String toURL()
@@ -348,15 +354,7 @@ public abstract class AMQDestination implements Destination, Referenceable
{
return false;
}
- /* if (_isExclusive != that._isExclusive)
- {
- return false;
- }
- if (_isAutoDelete != that._isAutoDelete)
- {
- return false;
- }
- */
+
return true;
}
@@ -370,8 +368,7 @@ public abstract class AMQDestination implements Destination, Referenceable
{
result = 29 * result + _queueName.hashCode();
}
-// result = result * (_isExclusive ? 13 : 7);
-// result = result * (_isAutoDelete ? 13 : 7);
+
return result;
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index 82f9a036d2..8bb5b622f7 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -202,6 +202,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
/** Responsible for decoding a message fragment and passing it to the appropriate message consumer. */
private static final Logger _dispatcherLogger = Logger.getLogger(Dispatcher.class);
+ private AtomicBoolean _firstDispatcher = new AtomicBoolean(true);
private class Dispatcher extends Thread
{
@@ -327,8 +328,11 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
") is closed rejecting(requeue)...");
}
}
-
- rejectMessage(message, true);
+ // Don't reject if we're already closing
+ if (!_closed.get())
+ {
+ rejectMessage(message, true);
+ }
}
else
{
@@ -995,42 +999,42 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
throw new java.lang.UnsupportedOperationException();
}
- public MessageProducer createProducer(Destination destination, boolean mandatory,
- boolean immediate, boolean waitUntilSent)
+ public BasicMessageProducer createProducer(Destination destination, boolean mandatory,
+ boolean immediate, boolean waitUntilSent)
throws JMSException
{
return createProducerImpl(destination, mandatory, immediate, waitUntilSent);
}
- public MessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate)
+ public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate)
throws JMSException
{
return createProducerImpl(destination, mandatory, immediate);
}
- public MessageProducer createProducer(Destination destination, boolean immediate)
+ public BasicMessageProducer createProducer(Destination destination, boolean immediate)
throws JMSException
{
return createProducerImpl(destination, DEFAULT_MANDATORY, immediate);
}
- public MessageProducer createProducer(Destination destination) throws JMSException
+ public BasicMessageProducer createProducer(Destination destination) throws JMSException
{
return createProducerImpl(destination, DEFAULT_MANDATORY, DEFAULT_IMMEDIATE);
}
- private org.apache.qpid.jms.MessageProducer createProducerImpl(Destination destination, boolean mandatory,
- boolean immediate)
+ private BasicMessageProducer createProducerImpl(Destination destination, boolean mandatory,
+ boolean immediate)
throws JMSException
{
return createProducerImpl(destination, mandatory, immediate, false);
}
- private org.apache.qpid.jms.MessageProducer createProducerImpl(final Destination destination, final boolean mandatory,
- final boolean immediate, final boolean waitUntilSent)
+ private BasicMessageProducer createProducerImpl(final Destination destination, final boolean mandatory,
+ final boolean immediate, final boolean waitUntilSent)
throws JMSException
{
- return (org.apache.qpid.jms.MessageProducer) new FailoverSupport()
+ return (BasicMessageProducer) new FailoverSupport()
{
public Object operation() throws JMSException
{
@@ -1248,8 +1252,10 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
JMSException ex = new JMSException("Error registering consumer: " + e);
- //todo remove
- e.printStackTrace();
+ if (_logger.isDebugEnabled())
+ {
+ e.printStackTrace();
+ }
ex.setLinkedException(e);
throw ex;
}
@@ -1926,6 +1932,24 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
synchronized void startDistpatcherIfNecessary()
{
+ if (Boolean.parseBoolean(System.getProperties().getProperty("REGISTER_CONSUMERS_FLOWED", "false")))
+ {
+// if (!connectionStopped)
+ {
+ if (isSuspended() && _firstDispatcher.getAndSet(false))
+ {
+ try
+ {
+ suspendChannel(false);
+ }
+ catch (AMQException e)
+ {
+ _logger.info("Suspending channel threw an exception:" + e);
+ }
+ }
+ }
+ }
+
startDistpatcherIfNecessary(false);
}
@@ -1974,6 +1998,27 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
bindQueue(amqd, queueName, protocolHandler, consumer.getRawSelectorFieldTable());
+ // The dispatcher will be null if we have just created this session
+ // so suspend the channel before we register our consumer so that we don't
+ // start prefetching until a receive/mListener is set.
+ if (Boolean.parseBoolean(System.getProperties().getProperty("REGISTER_CONSUMERS_FLOWED", "false")))
+ {
+ if (_dispatcher == null)
+ {
+ if (!isSuspended())
+ {
+ try
+ {
+ suspendChannel(true);
+ }
+ catch (AMQException e)
+ {
+ _logger.info("Suspending channel threw an exception:" + e);
+ }
+ }
+ }
+ }
+
try
{
consumeFromQueue(consumer, queueName, protocolHandler, nowait, consumer.getMessageSelector());
@@ -2089,7 +2134,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
// Remove the consumer from the map
BasicMessageConsumer consumer = (BasicMessageConsumer) _consumers.get(consumerTag);
if (consumer != null)
- {
+ {
// fixme this isn't right.. needs to check if _queue contains data for this consumer
if (consumer.isAutoClose())// && _queue.isEmpty())
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index 73010ce517..1c3cdbcb65 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -20,9 +20,9 @@
*/
package org.apache.qpid.client;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
-import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
@@ -34,6 +34,7 @@ import javax.jms.Message;
import javax.jms.MessageListener;
import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.client.message.MessageFactoryRegistry;
@@ -138,10 +139,10 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
private boolean _noConsume;
private List<StackTraceElement> _closedStack = null;
- protected BasicMessageConsumer(int channelId, AMQConnection connection, AMQDestination destination, String messageSelector,
- boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session,
- AMQProtocolHandler protocolHandler, FieldTable rawSelectorFieldTable,
- int prefetchHigh, int prefetchLow, boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose)
+ protected BasicMessageConsumer(int channelId, AMQConnection connection, AMQDestination destination,
+ String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session,
+ AMQProtocolHandler protocolHandler, FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow,
+ boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose)
{
_channelId = channelId;
_connection = connection;
@@ -160,7 +161,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_autoClose = autoClose;
_noConsume = noConsume;
- //Force queue browsers not to use acknowledge modes.
+ // Force queue browsers not to use acknowledge modes.
if (_noConsume)
{
_acknowledgeMode = Session.NO_ACKNOWLEDGE;
@@ -175,12 +176,14 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public String getMessageSelector() throws JMSException
{
checkPreConditions();
+
return _messageSelector;
}
public MessageListener getMessageListener() throws JMSException
{
checkPreConditions();
+
return _messageListener.get();
}
@@ -198,14 +201,14 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
checkPreConditions();
- //if the current listener is non-null and the session is not stopped, then
- //it is an error to call this method.
+ // if the current listener is non-null and the session is not stopped, then
+ // it is an error to call this method.
- //i.e. it is only valid to call this method if
+ // i.e. it is only valid to call this method if
//
- // (a) the connection is stopped, in which case the dispatcher is not running
- // OR
- // (b) the listener is null AND we are not receiving synchronously at present
+ // (a) the connection is stopped, in which case the dispatcher is not running
+ // OR
+ // (b) the listener is null AND we are not receiving synchronously at present
//
if (!_session.getAMQConnection().started())
@@ -215,7 +218,8 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
if (_logger.isDebugEnabled())
{
- _logger.debug("Session stopped : Message listener(" + messageListener + ") set for destination " + _destination);
+ _logger.debug("Session stopped : Message listener(" + messageListener + ") set for destination "
+ + _destination);
}
}
else
@@ -224,6 +228,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
throw new javax.jms.IllegalStateException("Another thread is already receiving synchronously.");
}
+
if (!_messageListener.compareAndSet(null, messageListener))
{
throw new javax.jms.IllegalStateException("Attempt to alter listener while session is started.");
@@ -233,7 +238,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
if (messageListener != null)
{
- //handle case where connection has already been started, and the dispatcher has alreaded started
+ // handle case where connection has already been started, and the dispatcher has alreaded started
// putting values on the _synchronousQueue
synchronized (_session)
@@ -263,10 +268,12 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
throw new javax.jms.IllegalStateException("Another thread is already receiving.");
}
+
if (isMessageListenerSet())
{
throw new javax.jms.IllegalStateException("A listener has already been set.");
}
+
_receivingThread = Thread.currentThread();
}
@@ -331,6 +338,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
return null;
}
+
Object o = null;
if (l > 0)
{
@@ -340,6 +348,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
o = _synchronousQueue.take();
}
+
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
{
@@ -352,6 +361,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
catch (InterruptedException e)
{
_logger.warn("Interrupted: " + e);
+
return null;
}
finally
@@ -365,6 +375,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
if (isAutoClose() && _closeWhenNoMessages && _synchronousQueue.isEmpty())
{
close(false);
+
return true;
}
else
@@ -387,6 +398,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
return null;
}
+
Object o = _synchronousQueue.poll();
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
@@ -414,8 +426,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
* @throws JMSException if the argument is a throwable. If it is a JMSException it is rethrown as is, but if not a
* JMSException is created with the linked exception set appropriately
*/
- private AbstractJMSMessage returnMessageOrThrow(Object o)
- throws JMSException
+ private AbstractJMSMessage returnMessageOrThrow(Object o) throws JMSException
{
// errors are passed via the queue too since there is no way of interrupting the poll() via the API.
if (o instanceof Throwable)
@@ -425,6 +436,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
e.setLinkedException((Exception) o);
}
+
throw e;
}
else
@@ -433,7 +445,6 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
-
public void close() throws JMSException
{
close(true);
@@ -441,7 +452,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public void close(boolean sendClose) throws JMSException
{
- //synchronized (_closed)
+ // synchronized (_closed)
if (_logger.isInfoEnabled())
{
@@ -456,7 +467,8 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
if (_closedStack != null)
{
- _logger.trace(_consumerTag + " close():" + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6));
+ _logger.trace(_consumerTag + " close():"
+ + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6));
_logger.trace(_consumerTag + " previously:" + _closedStack.toString());
}
else
@@ -464,14 +476,14 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_closedStack = Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6);
}
}
+
if (sendClose)
{
// TODO: Be aware of possible changes to parameter order as versions change.
- final AMQFrame cancelFrame = BasicCancelBody.createAMQFrame(_channelId,
- _protocolHandler.getProtocolMajorVersion(),
- _protocolHandler.getProtocolMinorVersion(),
- _consumerTag, // consumerTag
- false); // nowait
+ final AMQFrame cancelFrame =
+ BasicCancelBody.createAMQFrame(_channelId, _protocolHandler.getProtocolMajorVersion(),
+ _protocolHandler.getProtocolMinorVersion(), _consumerTag, // consumerTag
+ false); // nowait
try
{
@@ -485,25 +497,28 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
catch (AMQException e)
{
- _logger.error("Error closing consumer: " + e, e);
- throw new JMSException("Error closing consumer: " + e);
+ // _logger.error("Error closing consumer: " + e, e);
+ JMSException jmse = new JMSException("Error closing consumer: " + e);
+ jmse.setLinkedException(e);
+ throw jmse;
}
}
else
{
-// //fixme this probably is not right
-// if (!isNoConsume())
- { //done in BasicCancelOK Handler but not sending one so just deregister.
+ // //fixme this probably is not right
+ // if (!isNoConsume())
+ { // done in BasicCancelOK Handler but not sending one so just deregister.
deregisterConsumer();
}
}
- if (_messageListener != null && _receiving.get())
+ if ((_messageListener != null) && _receiving.get())
{
if (_logger.isInfoEnabled())
{
_logger.info("Interrupting thread: " + _receivingThread);
}
+
_receivingThread.interrupt();
}
}
@@ -516,7 +531,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
*/
void markClosed()
{
-// synchronized (_closed)
+ // synchronized (_closed)
{
_closed.set(true);
@@ -524,7 +539,8 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
if (_closedStack != null)
{
- _logger.trace(_consumerTag + " markClosed():" + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8));
+ _logger.trace(_consumerTag + " markClosed():"
+ + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8));
_logger.trace(_consumerTag + " previously:" + _closedStack.toString());
}
else
@@ -533,6 +549,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
}
+
deregisterConsumer();
}
@@ -551,22 +568,22 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_logger.debug("notifyMessage called with message number " + messageFrame.getDeliverBody().deliveryTag);
}
+
try
{
- AbstractJMSMessage jmsMessage = _messageFactory.createMessage(messageFrame.getDeliverBody().deliveryTag,
- messageFrame.getDeliverBody().redelivered,
- messageFrame.getDeliverBody().exchange,
- messageFrame.getDeliverBody().routingKey,
- messageFrame.getContentHeader(),
- messageFrame.getBodies());
+ AbstractJMSMessage jmsMessage =
+ _messageFactory.createMessage(messageFrame.getDeliverBody().deliveryTag,
+ messageFrame.getDeliverBody().redelivered, messageFrame.getDeliverBody().exchange,
+ messageFrame.getDeliverBody().routingKey, messageFrame.getContentHeader(), messageFrame.getBodies());
if (debug)
{
_logger.debug("Message is of type: " + jmsMessage.getClass().getName());
}
-// synchronized (_closed)
+ // synchronized (_closed)
+
{
-// if (!_closed.get())
+ // if (!_closed.get())
{
jmsMessage.setConsumer(this);
@@ -575,12 +592,12 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
notifyMessage(jmsMessage, channelId);
}
-// else
-// {
-// _logger.error("MESSAGE REJECTING!");
-// _session.rejectMessage(jmsMessage, true);
-// //_logger.error("MESSAGE JUST DROPPED!");
-// }
+ // else
+ // {
+ // _logger.error("MESSAGE REJECTING!");
+ // _session.rejectMessage(jmsMessage, true);
+ // //_logger.error("MESSAGE JUST DROPPED!");
+ // }
}
}
catch (Exception e)
@@ -606,11 +623,11 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
if (isMessageListenerSet())
{
- //we do not need a lock around the test above, and the dispatch below as it is invalid
- //for an application to alter an installed listener while the session is started
-// synchronized (_closed)
+ // we do not need a lock around the test above, and the dispatch below as it is invalid
+ // for an application to alter an installed listener while the session is started
+ // synchronized (_closed)
{
-// if (!_closed.get())
+ // if (!_closed.get())
{
preApplicationProcessing(jmsMessage);
@@ -641,9 +658,11 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
switch (_acknowledgeMode)
{
+
case Session.PRE_ACKNOWLEDGE:
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
break;
+
case Session.CLIENT_ACKNOWLEDGE:
// we set the session so that when the user calls acknowledge() it can call the method on session
// to send out the appropriate frame
@@ -657,17 +676,21 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
msg.setJMSDestination(_destination);
switch (_acknowledgeMode)
{
+
case Session.CLIENT_ACKNOWLEDGE:
if (isNoConsume())
{
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
}
+
break;
+
case Session.DUPS_OK_ACKNOWLEDGE:
if (++_outstanding >= _prefetchHigh)
{
_dups_ok_acknowledge_send = true;
}
+
if (_outstanding <= _prefetchLow)
{
_dups_ok_acknowledge_send = false;
@@ -680,14 +703,18 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_session.acknowledgeMessage(msg.getDeliveryTag(), true);
}
}
+
break;
+
case Session.AUTO_ACKNOWLEDGE:
// we do not auto ack a message if the application code called recover()
if (!_session.isInRecovery())
{
_session.acknowledgeMessage(msg.getDeliveryTag(), false);
}
+
break;
+
case Session.SESSION_TRANSACTED:
if (isNoConsume())
{
@@ -697,6 +724,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_receivedDeliveryTags.add(msg.getDeliveryTag());
}
+
break;
}
}
@@ -721,14 +749,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
void notifyError(Throwable cause)
{
-// synchronized (_closed)
+ // synchronized (_closed)
{
_closed.set(true);
if (_logger.isTraceEnabled())
{
if (_closedStack != null)
{
- _logger.trace(_consumerTag + " notifyError():" + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8));
+ _logger.trace(_consumerTag + " notifyError():"
+ + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8));
_logger.trace(_consumerTag + " previously" + _closedStack.toString());
}
else
@@ -737,7 +766,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
}
- //QPID-293 can "request redelivery of this error through dispatcher"
+ // QPID-293 can "request redelivery of this error through dispatcher"
// we have no way of propagating the exception to a message listener - a JMS limitation - so we
// deal with the case where we have a synchronous receive() waiting for a message to arrive
@@ -749,10 +778,10 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_logger.debug("Passed exception to synchronous queue for propagation to receive()");
}
}
+
deregisterConsumer();
}
-
/**
* Perform cleanup to deregister this consumer. This occurs when closing the consumer in both the clean case and in
* the case of an error occurring.
@@ -782,7 +811,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
this.checkNotClosed();
- if (_session == null || _session.isClosed())
+ if ((_session == null) || _session.isClosed())
{
throw new javax.jms.IllegalStateException("Invalid Session");
}
@@ -817,7 +846,6 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
return _autoClose;
}
-
public boolean isNoConsume()
{
return _noConsume;
@@ -827,10 +855,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_closeWhenNoMessages = b;
- if (_closeWhenNoMessages
- && _synchronousQueue.isEmpty()
- && _receiving.get()
- && _messageListener != null)
+ if (_closeWhenNoMessages && _synchronousQueue.isEmpty() && _receiving.get() && (_messageListener != null))
{
_receivingThread.interrupt();
}
@@ -846,13 +871,13 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
_logger.debug("Rejecting received messages in _receivedDTs (RQ)");
}
- //rollback received but not committed messages
+ // rollback received but not committed messages
while (!_receivedDeliveryTags.isEmpty())
{
if (_logger.isDebugEnabled())
{
- _logger.debug("Rejecting the messages(" + _receivedDeliveryTags.size() + ") in _receivedDTs (RQ)" +
- "for consumer with tag:" + _consumerTag);
+ _logger.debug("Rejecting the messages(" + _receivedDeliveryTags.size() + ") in _receivedDTs (RQ)"
+ + "for consumer with tag:" + _consumerTag);
}
Long tag = _receivedDeliveryTags.poll();
@@ -876,14 +901,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
- //rollback pending messages
+ // rollback pending messages
if (_synchronousQueue.size() > 0)
{
if (_logger.isDebugEnabled())
{
- _logger.debug("Rejecting the messages(" + _synchronousQueue.size() + ") in _syncQueue (PRQ)" +
- "for consumer with tag:" + _consumerTag);
+ _logger.debug("Rejecting the messages(" + _synchronousQueue.size() + ") in _syncQueue (PRQ)"
+ + "for consumer with tag:" + _consumerTag);
}
+
Iterator iterator = _synchronousQueue.iterator();
while (iterator.hasNext())
@@ -898,13 +924,14 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
_logger.trace("Rejected message:" + ((AbstractJMSMessage) o).getDeliveryTag());
}
+
iterator.remove();
}
else
{
- _logger.error("Queue contained a :" + o.getClass() +
- " unable to reject as it is not an AbstractJMSMessage. Will be cleared");
+ _logger.error("Queue contained a :" + o.getClass()
+ + " unable to reject as it is not an AbstractJMSMessage. Will be cleared");
iterator.remove();
}
}
@@ -919,7 +946,6 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
-
public String debugIdentity()
{
return String.valueOf(_consumerTag);
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index b01e087ce1..bd7cc94582 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -21,6 +21,7 @@
package org.apache.qpid.client;
import java.io.UnsupportedEncodingException;
+import java.util.UUID;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
@@ -118,6 +119,9 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
private final boolean _mandatory;
private final boolean _waitUntilSent;
+
+ private boolean _disableMessageId;
+
private static final ContentBody[] NO_CONTENT_BODIES = new ContentBody[0];
protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId,
@@ -172,15 +176,14 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
{
checkPreConditions();
checkNotClosed();
- // IGNORED
+ _disableMessageId = b;
}
public boolean getDisableMessageID() throws JMSException
{
checkNotClosed();
- // Always false for AMQP
- return false;
+ return _disableMessageId;
}
public void setDisableMessageTimestamp(boolean b) throws JMSException
@@ -450,6 +453,18 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
origMessage.setJMSDestination(destination);
AbstractJMSMessage message = convertToNativeMessage(origMessage);
+
+ if(_disableMessageId)
+ {
+ message.setJMSMessageID(null);
+ }
+ else
+ {
+ if (message.getJMSMessageID() == null)
+ {
+ message.setJMSMessageID(UUID.randomUUID().toString());
+ }
+ }
int type;
if (destination instanceof Topic)
@@ -667,4 +682,9 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
{
return _session;
}
+
+ public boolean isBound(AMQDestination destination) throws JMSException
+ {
+ return _session.isQueueBound(destination.getExchangeName(),null,destination.getRoutingKey());
+ }
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java
index d2ab6bd2c2..d1237cff49 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java
@@ -1,5 +1,25 @@
/*
*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+/*
+ *
* Copyright (c) 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,10 +42,35 @@ import javax.jms.JMSException;
import org.apache.qpid.AMQException;
/**
+ * JMSException does not accept wrapped exceptions in its constructor. Presumably this is because it is a relatively old
+ * Java exception class, before this was added as a default to Throwable. This exception class accepts wrapped exceptions
+ * as well as error messages, through its constructor, but is a JMSException.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Accept wrapped exceptions as a JMSException.
+ * </table>
+ *
* @author Apache Software Foundation
*/
public class JMSAMQException extends JMSException
{
+ /**
+ * Creates a JMSException, wrapping another exception class.
+ *
+ * @param message The error message.
+ * @param cause The underlying exception that caused this one. May be null if none is to be set.
+ */
+ public JMSAMQException(String message, Exception cause)
+ {
+ super(message);
+
+ if (cause != null)
+ {
+ setLinkedException(cause);
+ }
+ }
+
public JMSAMQException(AMQException s)
{
super(s.getMessage(), String.valueOf(s.getErrorCode()));
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
index c9d29d8077..e0c4b61333 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
@@ -7,14 +7,15 @@ import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueSender;
+import javax.jms.InvalidDestinationException;
public class QueueSenderAdapter implements QueueSender {
- private MessageProducer _delegate;
+ private BasicMessageProducer _delegate;
private Queue _queue;
private boolean closed = false;
- public QueueSenderAdapter(MessageProducer msgProducer, Queue queue){
+ public QueueSenderAdapter(BasicMessageProducer msgProducer, Queue queue){
_delegate = msgProducer;
_queue = queue;
}
@@ -122,12 +123,13 @@ public class QueueSenderAdapter implements QueueSender {
_delegate.setTimeToLive(timeToLive);
}
- private void checkPreConditions() throws IllegalStateException, IllegalStateException
+ private void checkPreConditions() throws JMSException
{
checkPreConditions(_queue);
}
- private void checkPreConditions(Queue queue) throws IllegalStateException, IllegalStateException {
+ private void checkPreConditions(Queue queue) throws JMSException
+ {
if (closed){
throw new javax.jms.IllegalStateException("Publisher is closed");
}
@@ -137,5 +139,28 @@ public class QueueSenderAdapter implements QueueSender {
if(session == null || session.isClosed()){
throw new javax.jms.IllegalStateException("Invalid Session");
}
- }
+
+ if(!(queue instanceof AMQDestination))
+ {
+ throw new InvalidDestinationException("Queue: " + queue + " is not a valid Qpid queue");
+ }
+ AMQDestination destination = (AMQDestination) queue;
+ if(!destination.isValidated() && checkQueueBeforePublish())
+ {
+
+ if (_delegate.isBound(destination))
+ {
+ destination.setValidated(true);
+ }
+ else
+ {
+ throw new InvalidDestinationException("Queue: " + queue + " is not a valid destination (no bindings on server");
+ }
+ }
+ }
+
+ private boolean checkQueueBeforePublish()
+ {
+ return "true".equalsIgnoreCase(System.getProperty("org.apache.qpid.client.verifyQueueBindingBeforePublish", "true"));
+ }
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/TopicPublisherAdapter.java b/qpid/java/client/src/main/java/org/apache/qpid/client/TopicPublisherAdapter.java
index f67b984658..02a408465b 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/TopicPublisherAdapter.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/TopicPublisherAdapter.java
@@ -175,5 +175,10 @@ public class TopicPublisherAdapter implements TopicPublisher
{
throw new InvalidDestinationException("Destination " + topic + " is not a topic");
}
+ if(!(topic instanceof AMQDestination))
+ {
+ throw new InvalidDestinationException("Destination " + topic + " is not a Qpid topic");
+ }
+
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
index e2b101ab79..f62baf2c3a 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java
@@ -94,6 +94,8 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener
}
}
+ //fixme why is this only done when the close is expected...
+ // should the above forced closes not also cause a close?
protocolSession.channelClosed(evt.getChannelId(), errorCode, String.valueOf(reason));
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
index 8938130417..af254fbbaf 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractBytesMessage.java
@@ -27,6 +27,7 @@ import javax.jms.JMSException;
import javax.jms.MessageEOFException;
import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -72,7 +73,7 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
}
AbstractBytesMessage(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ AMQShortString routingKey, ByteBuffer data) throws AMQException
{
// TODO: this casting is ugly. Need to review whole ContentHeaderBody idea
super(messageNbr, (BasicContentHeaderProperties) contentHeader.properties, exchange, routingKey, data);
@@ -93,7 +94,9 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
}
catch (IOException e)
{
- throw new JMSException(e.toString());
+ JMSException jmse = new JMSException(e.toString());
+ jmse.setLinkedException(e);
+ throw jmse;
}
}
@@ -112,6 +115,7 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
{
return null;
}
+
int pos = _data.position();
_data.rewind();
// one byte left is for the end of frame marker
@@ -119,12 +123,14 @@ public abstract class AbstractBytesMessage extends AbstractJMSMessage
{
// this is really redundant since pos must be zero
_data.position(pos);
+
return null;
}
else
{
String data = _data.getString(Charset.forName("UTF8").newDecoder());
_data.position(pos);
+
return data;
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
index 66524edce3..f87b4027f6 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
@@ -23,6 +23,7 @@ package org.apache.qpid.client.message;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
+import java.util.UUID;
import javax.jms.Destination;
import javax.jms.JMSException;
@@ -32,12 +33,7 @@ import javax.jms.MessageNotWriteableException;
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.AMQUndefinedDestination;
-import org.apache.qpid.client.BasicMessageConsumer;
-import org.apache.qpid.client.CustomJMSXProperty;
+import org.apache.qpid.client.*;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
@@ -123,7 +119,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
{
if (getContentHeaderProperties().getMessageIdAsString() == null)
{
- getContentHeaderProperties().setMessageId("ID:" + _deliveryTag);
+ getContentHeaderProperties().setMessageId("ID:" + UUID.randomUUID());
}
return getContentHeaderProperties().getMessageIdAsString();
@@ -183,7 +179,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach
}
catch (URLSyntaxException e)
{
- throw new JMSException("Illegal value in JMS_ReplyTo property: " + replyToEncoding);
+ throw new JMSAMQException("Illegal value in JMS_ReplyTo property: " + replyToEncoding, e);
}
_destinationCache.put(replyToEncoding, dest);
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 6352f7029f..348a0bd152 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
@@ -384,7 +384,9 @@ public final class JMSHeaderAdapter
}
catch (AMQPInvalidClassException aice)
{
- throw new MessageFormatException("Only primatives are allowed object is:" + object.getClass());
+ MessageFormatException mfe = new MessageFormatException("Only primatives are allowed object is:" + object.getClass());
+ mfe.setLinkedException(aice);
+ throw mfe;
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
index df1400b167..caf8741280 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
@@ -33,6 +33,7 @@ import javax.jms.MessageFormatException;
import javax.jms.ObjectMessage;
import org.apache.mina.common.ByteBuffer;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
@@ -61,14 +62,15 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
_data = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
_data.setAutoExpand(true);
}
+
getContentHeaderProperties().setContentType(MIME_TYPE_SHORT_STRING);
}
/**
* Creates read only message for delivery to consumers
*/
- JMSObjectMessage(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange,
- AMQShortString routingKey, ByteBuffer data) throws AMQException
+ JMSObjectMessage(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange, AMQShortString routingKey,
+ ByteBuffer data) throws AMQException
{
super(messageNbr, (BasicContentHeaderProperties) contentHeader.properties, exchange, routingKey, data);
}
@@ -79,6 +81,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
{
_data.release();
}
+
_data = null;
}
@@ -116,11 +119,13 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
}
catch (IOException e)
{
- throw new MessageFormatException("Message not serializable: " + e);
+ MessageFormatException mfe = new MessageFormatException("Message not serializable: " + e);
+ mfe.setLinkedException(e);
+ throw mfe;
}
}
-
+
public Serializable getObject() throws JMSException
{
ObjectInputStream in = null;
@@ -133,17 +138,20 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
{
_data.rewind();
in = new ObjectInputStream(_data.asInputStream());
+
return (Serializable) in.readObject();
}
catch (IOException e)
{
- e.printStackTrace();
- throw new MessageFormatException("Could not deserialize message: " + e);
+ MessageFormatException mfe = new MessageFormatException("Could not deserialize message: " + e);
+ mfe.setLinkedException(e);
+ throw mfe;
}
catch (ClassNotFoundException e)
{
- e.printStackTrace();
- throw new MessageFormatException("Could not deserialize message: " + e);
+ MessageFormatException mfe = new MessageFormatException("Could not deserialize message: " + e);
+ mfe.setLinkedException(e);
+ throw mfe;
}
finally
{
@@ -162,8 +170,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
}
}
catch (IOException ignore)
- {
- }
+ { }
}
private static String toString(ByteBuffer data)
@@ -172,6 +179,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
{
return null;
}
+
int pos = data.position();
try
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index d0cc52271a..5bc1555df7 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -34,6 +34,7 @@ import org.apache.qpid.AMQConnectionClosedException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQTimeoutException;
+import org.apache.qpid.AMQChannelClosedException;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.SSLConfiguration;
@@ -248,6 +249,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter
sessionClosed(session);
}
+
+ //FIXME Need to correctly handle other exceptions. Things like ...
+// if (cause instanceof AMQChannelClosedException)
+ // which will cause the JMSSession to end due to a channel close and so that Session needs
+ // to be removed from the map so we can correctly still call close without an exception when trying to close
+ // the server closed session. See also CloseChannelMethodHandler as the sessionClose is never called on exception
}
// we reach this point if failover was attempted and failed therefore we need to let the calling app
// know since we cannot recover the situation
@@ -510,11 +517,6 @@ public class AMQProtocolHandler extends IoHandlerAdapter
_protocolSession.closeSession(session);
}
- public void closeConnection() throws AMQException
- {
- closeConnection(-1);
- }
-
public void closeConnection(long timeout) throws AMQException
{
getStateManager().changeState(AMQState.CONNECTION_CLOSING);
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties b/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
index 50e6f1efaa..89ee8337f8 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
@@ -16,5 +16,6 @@
# specific language governing permissions and limitations
# under the License.
#
+CallbackHandler.CRAM-MD5-HASHED=org.apache.qpid.client.security.UsernameHashedPasswordCallbackHandler
CallbackHandler.CRAM-MD5=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
CallbackHandler.PLAIN=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
index f8ee22a5d9..04db8044de 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java
@@ -20,10 +20,6 @@
*/
package org.apache.qpid.client.security;
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.Security;
@@ -34,6 +30,7 @@ import java.util.TreeMap;
import javax.security.sasl.SaslClientFactory;
+
import org.apache.log4j.Logger;
import org.apache.qpid.util.FileUtils;
@@ -50,14 +47,11 @@ import org.apache.qpid.util.FileUtils;
* mechanism=fully.qualified.class.name
* </pre>
*
- * <p/>Where mechanism is an IANA-registered mechanism name and the fully qualified class name refers to a
- * class that implements javax.security.sasl.SaslClientFactory and provides the specified mechanism.
+ * <p/>Where mechanism is an IANA-registered mechanism name and the fully qualified class name refers to a class that
+ * implements javax.security.sasl.SaslClientFactory and provides the specified mechanism.
*
- * <p><table id="crc"><caption>CRC Card</caption>
- * <tr><th> Responsibilities <th> Collaborations
- * <tr><td> Parse SASL mechanism properties.
- * <tr><td> Create and register security provider for SASL mechanisms.
- * </table>
+ * <p><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Parse SASL
+ * mechanism properties. <tr><td> Create and register security provider for SASL mechanisms. </table>
*/
public class DynamicSaslRegistrar
{
@@ -69,10 +63,7 @@ public class DynamicSaslRegistrar
/** The default name of the SASL properties file resource. */
public static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/client/security/DynamicSaslRegistrar.properties";
- /**
- * Reads the properties file, and creates a dynamic security provider to register the SASL implementations
- * with.
- */
+ /** Reads the properties file, and creates a dynamic security provider to register the SASL implementations with. */
public static void registerSaslProviders()
{
_logger.debug("public static void registerSaslProviders(): called");
@@ -80,8 +71,8 @@ public class DynamicSaslRegistrar
// Open the SASL properties file, using the default name is one is not specified.
String filename = System.getProperty(FILE_PROPERTY);
InputStream is =
- FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
- DynamicSaslRegistrar.class.getClassLoader());
+ FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
+ DynamicSaslRegistrar.class.getClassLoader());
try
{
@@ -94,7 +85,7 @@ public class DynamicSaslRegistrar
if (factories.size() > 0)
{
- Security.addProvider(new JCAProvider(factories));
+ Security.insertProviderAt(new JCAProvider(factories), 0);
_logger.debug("Dynamic SASL provider added as a security provider");
}
}
@@ -170,15 +161,15 @@ public class DynamicSaslRegistrar
* @return A map from SASL mechanism names to implementing client factory classes.
*
* @todo Why tree map here? Do really want mechanisms in alphabetical order? Seems more likely that the declared
- * order of the mechanisms is intended to be preserved, so that they are registered in the declared order
- * of preference. Consider LinkedHashMap instead.
+ * order of the mechanisms is intended to be preserved, so that they are registered in the declared order of
+ * preference. Consider LinkedHashMap instead.
*/
private static Map<String, Class<? extends SaslClientFactory>> parseProperties(Properties props)
{
Enumeration e = props.propertyNames();
TreeMap<String, Class<? extends SaslClientFactory>> factoriesToRegister =
- new TreeMap<String, Class<? extends SaslClientFactory>>();
+ new TreeMap<String, Class<? extends SaslClientFactory>>();
while (e.hasMoreElements())
{
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
index c2a7d7928c..1bff43142b 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
@@ -17,3 +17,4 @@
# under the License.
#
AMQPLAIN=org.apache.qpid.client.security.amqplain.AmqPlainSaslClientFactory
+CRAM-MD5-HASHED=org.apache.qpid.client.security.crammd5hashed.CRAMMD5HashedSaslClientFactory
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java b/qpid/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
index 2fa8dcddde..5bf120454e 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java
@@ -52,7 +52,7 @@ public class JCAProvider extends Provider
super("AMQSASLProvider", 1.0, "A JCA provider that registers all "
+ "AMQ SASL providers that want to be registered");
register(providerMap);
- Security.addProvider(this);
+// Security.addProvider(this);
}
/**
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
new file mode 100644
index 0000000000..46323e8c09
--- /dev/null
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java
@@ -0,0 +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.client.security;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.RealmCallback;
+
+import com.sun.crypto.provider.HmacMD5;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.client.protocol.AMQProtocolSession;
+
+public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler
+{
+ private static final Logger _logger = Logger.getLogger(UsernameHashedPasswordCallbackHandler.class);
+
+ private AMQProtocolSession _protocolSession;
+
+ public void initialise(AMQProtocolSession protocolSession)
+ {
+ _protocolSession = protocolSession;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ Callback cb = callbacks[i];
+ if (cb instanceof NameCallback)
+ {
+ ((NameCallback) cb).setName(_protocolSession.getUsername());
+ }
+ else if (cb instanceof PasswordCallback)
+ {
+ try
+ {
+ ((PasswordCallback) cb).setPassword(getHash(_protocolSession.getPassword()));
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ UnsupportedCallbackException uce = new UnsupportedCallbackException(cb);
+ uce.initCause(e);
+ throw uce;
+ }
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(cb);
+ }
+ }
+ }
+
+ private char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
+ {
+
+ byte[] data = text.getBytes("utf-8");
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ for (byte b : data)
+ {
+ md.update(b);
+ }
+
+ byte[] digest = md.digest();
+
+ char[] hash = new char[digest.length ];
+
+ int index = 0;
+ for (byte b : digest)
+ {
+ hash[index++] = (char) b;
+ }
+
+ return hash;
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java b/qpid/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java
new file mode 100644
index 0000000000..22bb1ac156
--- /dev/null
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/crammd5hashed/CRAMMD5HashedSaslClientFactory.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+package org.apache.qpid.client.security.crammd5hashed;
+
+import org.apache.qpid.client.security.amqplain.AmqPlainSaslClient;
+
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.Sasl;
+import javax.security.auth.callback.CallbackHandler;
+import java.util.Map;
+import java.security.Security;
+
+public class CRAMMD5HashedSaslClientFactory implements SaslClientFactory
+{
+ /** The name of this mechanism */
+ public static final String MECHANISM = "CRAM-MD5-HASHED";
+
+
+ public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName, Map<String, ?> props, CallbackHandler cbh) throws SaslException
+ {
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ if (mechanisms[i].equals(MECHANISM))
+ {
+ if (cbh == null)
+ {
+ throw new SaslException("CallbackHandler must not be null");
+ }
+
+ String[] mechs = {"CRAM-MD5"};
+ return Sasl.createSaslClient(mechs, authorizationId, protocol, serverName, props, cbh);
+ }
+ }
+ return null;
+ }
+
+ public String[] getMechanismNames(Map props)
+ {
+ if (props != null)
+ {
+ if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE))
+ {
+ // returned array must be non null according to interface documentation
+ return new String[0];
+ }
+ }
+
+ return new String[]{MECHANISM};
+ }
+}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQNoTransportForProtocolException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQNoTransportForProtocolException.java
index 104c5bfc44..1ec3adc2eb 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQNoTransportForProtocolException.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQNoTransportForProtocolException.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -33,7 +33,7 @@ public class AMQNoTransportForProtocolException extends AMQTransportConnectionEx
public AMQNoTransportForProtocolException(BrokerDetails details, String message)
{
- super(message);
+ super(null, message, null);
_details = details;
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQTransportConnectionException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQTransportConnectionException.java
index 4b17661bc3..fec7ff693c 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQTransportConnectionException.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/AMQTransportConnectionException.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,12 +21,12 @@
package org.apache.qpid.client.transport;
import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
public class AMQTransportConnectionException extends AMQException
{
- public AMQTransportConnectionException(String message)
+ public AMQTransportConnectionException(AMQConstant errorCode, String message, Throwable cause)
{
- super(message);
-
+ super(errorCode, message, cause);
}
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
index 8368eee125..0bc83e9804 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -26,12 +26,14 @@ import java.util.Iterator;
import java.util.Map;
import org.apache.log4j.Logger;
+
import org.apache.mina.common.IoConnector;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoServiceConfig;
import org.apache.mina.transport.socket.nio.SocketConnector;
import org.apache.mina.transport.vmpipe.VmPipeAcceptor;
import org.apache.mina.transport.vmpipe.VmPipeAddress;
+
import org.apache.qpid.client.AMQBrokerDetails;
import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
import org.apache.qpid.jms.BrokerDetails;
@@ -64,13 +66,11 @@ public class TransportConnection
int transport = getTransport(details.getTransport());
if (transport == -1)
-
{
throw new AMQNoTransportForProtocolException(details);
}
if (transport == _currentInstance)
-
{
if (transport == VM)
{
@@ -88,40 +88,42 @@ public class TransportConnection
_currentInstance = transport;
switch (transport)
-
{
- case TCP:
- _instance = new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
- {
- public IoConnector newSocketConnector()
+
+ case TCP:
+ _instance = new SocketTransportConnection(new SocketTransportConnection.SocketConnectorFactory()
{
- SocketConnector result;
- //FIXME - this needs to be sorted to use the new Mina MultiThread SA.
- if (Boolean.getBoolean("qpidnio"))
+ public IoConnector newSocketConnector()
{
- _logger.fatal("Using Qpid NIO - sysproperty 'qpidnio' is set.");
-// result = new org.apache.qpid.nio.SocketConnector(); // non-blocking connector
+ SocketConnector result;
+ // FIXME - this needs to be sorted to use the new Mina MultiThread SA.
+ if (Boolean.getBoolean("qpidnio"))
+ {
+ _logger.fatal("Using Qpid NIO - sysproperty 'qpidnio' is set.");
+ // result = new org.apache.qpid.nio.SocketConnector(); // non-blocking connector
+ }
+ // else
+
+ {
+ _logger.info("Using Mina NIO");
+ result = new SocketConnector(); // non-blocking connector
+ }
+
+ // Don't have the connector's worker thread wait around for other connections (we only use
+ // one SocketConnector per connection at the moment anyway). This allows short-running
+ // clients (like unit tests) to complete quickly.
+ result.setWorkerTimeout(0);
+
+ return result;
}
-// else
- {
- _logger.info("Using Mina NIO");
- result = new SocketConnector(); // non-blocking connector
- }
-
- // Don't have the connector's worker thread wait around for other connections (we only use
- // one SocketConnector per connection at the moment anyway). This allows short-running
- // clients (like unit tests) to complete quickly.
- result.setWorkerTimeout(0);
+ });
+ break;
- return result;
- }
- });
- break;
- case VM:
- {
- _instance = getVMTransport(details, Boolean.getBoolean("amqj.AutoCreateVMBroker"));
- break;
- }
+ case VM:
+ {
+ _instance = getVMTransport(details, Boolean.getBoolean("amqj.AutoCreateVMBroker"));
+ break;
+ }
}
return _instance;
@@ -142,7 +144,8 @@ public class TransportConnection
return -1;
}
- private static ITransportConnection getVMTransport(BrokerDetails details, boolean AutoCreate) throws AMQVMBrokerCreationException
+ private static ITransportConnection getVMTransport(BrokerDetails details, boolean AutoCreate)
+ throws AMQVMBrokerCreationException
{
int port = details.getPort();
@@ -154,14 +157,14 @@ public class TransportConnection
}
else
{
- throw new AMQVMBrokerCreationException(port, "VM Broker on port " + port + " does not exist. Auto create disabled.");
+ throw new AMQVMBrokerCreationException(null, port, "VM Broker on port " + port
+ + " does not exist. Auto create disabled.", null);
}
}
return new VmPipeTransportConnection(port);
}
-
public static void createVMBroker(int port) throws AMQVMBrokerCreationException
{
if (_acceptor == null)
@@ -192,7 +195,7 @@ public class TransportConnection
{
_logger.error(e);
- //Try and unbind provider
+ // Try and unbind provider
try
{
VmPipeAddress pipe = new VmPipeAddress(port);
@@ -203,7 +206,7 @@ public class TransportConnection
}
catch (Exception ignore)
{
- //ignore
+ // ignore
}
if (provider == null)
@@ -227,7 +230,7 @@ public class TransportConnection
because = e.getCause().toString();
}
- throw new AMQVMBrokerCreationException(port, because + " Stopped binding of InVM Qpid.AMQP");
+ throw new AMQVMBrokerCreationException(null, port, because + " Stopped binding of InVM Qpid.AMQP", e);
}
}
}
@@ -246,14 +249,14 @@ public class TransportConnection
// can't use introspection to get Provider as it is a server class.
// need to go straight to IoHandlerAdapter but that requries the queues and exchange from the ApplicationRegistry which we can't access.
- //get right constructor and pass in instancec ID - "port"
+ // get right constructor and pass in instancec ID - "port"
IoHandlerAdapter provider;
try
{
- Class[] cnstr = {Integer.class};
- Object[] params = {port};
+ Class[] cnstr = { Integer.class };
+ Object[] params = { port };
provider = (IoHandlerAdapter) Class.forName(protocolProviderClass).getConstructor(cnstr).newInstance(params);
- //Give the broker a second to create
+ // Give the broker a second to create
_logger.info("Created VMBroker Instance:" + port);
}
catch (Exception e)
@@ -270,8 +273,10 @@ public class TransportConnection
because = e.getCause().toString();
}
-
- throw new AMQVMBrokerCreationException(port, because + " Stopped InVM Qpid.AMQP creation");
+ AMQVMBrokerCreationException amqbce =
+ new AMQVMBrokerCreationException(null, port, because + " Stopped InVM Qpid.AMQP creation", null);
+ amqbce.initCause(e);
+ throw amqbce;
}
return provider;
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java b/qpid/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java
index 607ddcc26a..4b2982fe9c 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/vmbroker/AMQVMBrokerCreationException.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,19 +21,25 @@
package org.apache.qpid.client.vmbroker;
import org.apache.qpid.client.transport.AMQTransportConnectionException;
+import org.apache.qpid.protocol.AMQConstant;
public class AMQVMBrokerCreationException extends AMQTransportConnectionException
{
private int _port;
+ /**
+ * @param port
+ *
+ * @deprecated
+ */
public AMQVMBrokerCreationException(int port)
{
- this(port, "Unable to create vm broker");
+ this(null, port, "Unable to create vm broker", null);
}
- public AMQVMBrokerCreationException(int port, String message)
+ public AMQVMBrokerCreationException(AMQConstant errorCode, int port, String message, Throwable cause)
{
- super(message);
+ super(errorCode, message, cause);
_port = port;
}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java b/qpid/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
index 9adf04e182..6ad3fb4bae 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java
@@ -101,7 +101,7 @@ public class FailoverPolicy
}
catch (Exception cnfe)
{
- throw new IllegalArgumentException("Unknown failover method:" + failoverMethod);
+ throw new IllegalArgumentException("Unknown failover method:" + failoverMethod, cnfe);
}
}
}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
index a406f9f86e..794fd5c8c1 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java
@@ -65,6 +65,7 @@ public class MessageListenerMultiConsumerTest extends TestCase
private final CountDownLatch _allMessagesSent = new CountDownLatch(2); //all messages Sent Lock
+
protected void setUp() throws Exception
{
super.setUp();
@@ -122,30 +123,39 @@ public class MessageListenerMultiConsumerTest extends TestCase
TransportConnection.killAllVMBrokers();
}
+// public void testRecieveC1thenC2() throws Exception
+// {
+//
+// for (int msg = 0; msg < MSG_COUNT / 2; msg++)
+// {
+//
+// assertTrue(_consumer1.receive() != null);
+// }
+//
+// for (int msg = 0; msg < MSG_COUNT / 2; msg++)
+// {
+// assertTrue(_consumer2.receive() != null);
+// }
+// }
- public void testRecieveC1thenC2() throws Exception
+ public void testRecieveInterleaved() throws Exception
{
-
- for (int msg = 0; msg < MSG_COUNT / 2; msg++)
+ int msg = 0;
+ int MAX_LOOPS = MSG_COUNT * 2;
+ for (int loops = 0; msg < MSG_COUNT || loops < MAX_LOOPS; loops++)
{
- assertTrue(_consumer1.receive() != null);
- }
-
- for (int msg = 0; msg < MSG_COUNT / 2; msg++)
- {
- assertTrue(_consumer2.receive() != null);
+ if (_consumer1.receive(100) != null)
+ {
+ msg++;
+ }
+ if (_consumer2.receive(100) != null)
+ {
+ msg++;
+ }
}
- }
-
- public void testRecieveInterleaved() throws Exception
- {
- for (int msg = 0; msg < MSG_COUNT / 2; msg++)
- {
- assertTrue(_consumer1.receive() != null);
- assertTrue(_consumer2.receive() != null);
- }
+ assertEquals("Not all messages received.", MSG_COUNT, msg);
}
@@ -161,7 +171,7 @@ public class MessageListenerMultiConsumerTest extends TestCase
if (receivedCount1 == MSG_COUNT / 2)
{
- _allMessagesSent.countDown();
+ _allMessagesSent.countDown();
}
}
@@ -196,6 +206,18 @@ public class MessageListenerMultiConsumerTest extends TestCase
assertEquals(MSG_COUNT, receivedCount1 + receivedCount2);
}
+ public void testRecieveC2Only_OnlyRunWith_REGISTER_CONSUMERS_FLOWED() throws Exception
+ {
+ if (Boolean.parseBoolean(System.getProperties().getProperty("REGISTER_CONSUMERS_FLOWED", "false")))
+ {
+ for (int msg = 0; msg < MSG_COUNT; msg++)
+ {
+ assertTrue(MSG_COUNT + " msg should be received. Only received:" + msg,
+ _consumer2.receive(1000) != null);
+ }
+ }
+ }
+
public static junit.framework.Test suite()
{
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java
index 5fb77af4db..7b5957ac8c 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java
@@ -144,6 +144,36 @@ public class MessageListenerTest extends TestCase implements MessageListener
}
+ public void testRecieveTheUseMessageListener() throws Exception
+ {
+
+ _logger.error("Test disabled as initial receive is not called first");
+ // Perform initial receive to start connection
+// assertTrue(_consumer.receive(2000) != null);
+// receivedCount++;
+
+ // Sleep to ensure remaining 4 msgs end up on _synchronousQueue
+// Thread.sleep(1000);
+
+ // Set the message listener and wait for the messages to come in.
+ _consumer.setMessageListener(this);
+
+ _logger.info("Waiting 3 seconds for messages");
+
+ try
+ {
+ _awaitMessages.await(3000, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e)
+ {
+ //do nothing
+ }
+ //Should have recieved all async messages
+ assertEquals(MSG_COUNT, receivedCount);
+
+ }
+
+
public void onMessage(Message message)
{
_logger.info("Received Message(" + receivedCount + "):" + message);
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java b/qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java
index 10bf1a8d6d..42594fff8e 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java
@@ -83,7 +83,7 @@ public class ResetMessageListenerTest extends TestCase
Hashtable<String, String> env = new Hashtable<String, String>();
env.put("connectionfactory.connection", "amqp://guest:guest@MLT_ID/test?brokerlist='vm://:1'");
- env.put("queue.queue", "direct://amq.direct//MessageListenerTest");
+ env.put("queue.queue", "direct://amq.direct//ResetMessageListenerTest");
_context = factory.getInitialContext(env);
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
new file mode 100644
index 0000000000..1b5da2631d
--- /dev/null
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
@@ -0,0 +1,109 @@
+package org.apache.qpid.test.unit.basic;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
+import org.apache.qpid.client.transport.TransportConnection;
+
+import junit.framework.TestCase;
+
+import javax.jms.MessageConsumer;
+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 TestCase
+{
+ private AMQConnection _connection;
+ private AMQDestination _destination;
+ private AMQSession _session;
+ private MessageConsumer _consumer;
+
+ private static final String VM_BROKER = "vm://:1";
+
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ createVMBroker();
+ _connection = new AMQConnection(VM_BROKER, "guest", "guest", "ReceiveTestClient", "test");
+ }
+
+ public void createVMBroker()
+ {
+ try
+ {
+ TransportConnection.createVMBroker(1);
+ }
+ catch (AMQVMBrokerCreationException e)
+ {
+ fail("Unable to create broker: " + e);
+ }
+ }
+
+ protected void tearDown() throws Exception
+ {
+ _connection.close();
+ TransportConnection.killVMBroker(1);
+ 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 :-(
+ MessageConsumer consumer = 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/close/MessageRequeueTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
index 7762cb3fe9..62234ad21f 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java
@@ -330,7 +330,7 @@ public class MessageRequeueTest extends TestCase
public void testRequeue() throws JMSException, AMQException, URLSyntaxException
{
int run = 0;
- while (run < 10)
+// while (run < 10)
{
run++;
@@ -350,17 +350,10 @@ public class MessageRequeueTest extends TestCase
_logger.debug("Create Consumer");
MessageConsumer consumer = session.createConsumer(q);
- try
- {
- Thread.sleep(2000);
- }
- catch (InterruptedException e)
- {
- //
- }
+ conn.start();
_logger.debug("Receiving msg");
- Message msg = consumer.receive(1000);
+ Message msg = consumer.receive(2000);
assertNotNull("Message should not be null", msg);
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
index 0828ab398c..190b3861f0 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java
@@ -100,7 +100,9 @@ public class DurableSubscriptionTest extends TestCase
AMQTopic topic = new AMQTopic(con,"MyTopic");
Session session1 = con.createSession(false, AMQSession.NO_ACKNOWLEDGE);
MessageConsumer consumer1 = session1.createConsumer(topic);
- MessageProducer producer = session1.createProducer(topic);
+
+ Session sessionProd = con.createSession(false, AMQSession.NO_ACKNOWLEDGE);
+ MessageProducer producer = sessionProd.createProducer(topic);
Session session2 = con.createSession(false, AMQSession.NO_ACKNOWLEDGE);
TopicSubscriber consumer2 = session2.createDurableSubscriber(topic, "MySubscription");
@@ -112,12 +114,12 @@ public class DurableSubscriptionTest extends TestCase
Message msg;
msg = consumer1.receive();
assertEquals("A", ((TextMessage) msg).getText());
- msg = consumer1.receive(1000);
+ msg = consumer1.receive(100);
assertEquals(null, msg);
msg = consumer2.receive();
assertEquals("A", ((TextMessage) msg).getText());
- msg = consumer2.receive(1000);
+ msg = consumer2.receive(100);
assertEquals(null, msg);
consumer2.close();
@@ -127,14 +129,14 @@ public class DurableSubscriptionTest extends TestCase
producer.send(session1.createTextMessage("B"));
- msg = consumer1.receive();
+ msg = consumer1.receive(100);
assertEquals("B", ((TextMessage) msg).getText());
- msg = consumer1.receive(1000);
+ msg = consumer1.receive(100);
assertEquals(null, msg);
- msg = consumer3.receive();
+ msg = consumer3.receive(100);
assertEquals("B", ((TextMessage) msg).getText());
- msg = consumer3.receive(1000);
+ msg = consumer3.receive(100);
assertEquals(null, msg);
con.close();
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
index 2abc139ced..685fe20048 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java
@@ -53,12 +53,15 @@ public class CommitRollbackTest extends TestCase
Queue _jmsQueue;
private static final Logger _logger = Logger.getLogger(CommitRollbackTest.class);
+ private static final String BROKER = "vm://:1";
protected void setUp() throws Exception
{
super.setUp();
- TransportConnection.createVMBroker(1);
-
+ if (BROKER.startsWith("vm"))
+ {
+ TransportConnection.createVMBroker(1);
+ }
testMethod++;
queue += testMethod;
@@ -68,7 +71,7 @@ public class CommitRollbackTest extends TestCase
private void newConnection() throws AMQException, URLSyntaxException, JMSException
{
- conn = new AMQConnection("amqp://guest:guest@client/test?brokerlist='vm://:1'");
+ conn = new AMQConnection("amqp://guest:guest@client/test?brokerlist='" + BROKER + "'");
_session = conn.createSession(true, Session.CLIENT_ACKNOWLEDGE);
@@ -87,7 +90,10 @@ public class CommitRollbackTest extends TestCase
super.tearDown();
conn.close();
- TransportConnection.killVMBroker(1);
+ if (BROKER.startsWith("vm"))
+ {
+ TransportConnection.killVMBroker(1);
+ }
}
/**
@@ -261,7 +267,7 @@ public class CommitRollbackTest extends TestCase
assertTrue("session is not transacted", _pubSession.getTransacted());
_logger.info("sending test message");
- String MESSAGE_TEXT = "testGetThenDisconnect";
+ String MESSAGE_TEXT = "testGetThenRollback";
_publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
_pubSession.commit();
@@ -394,16 +400,60 @@ public class CommitRollbackTest extends TestCase
_logger.info("receiving result");
result = _consumer.receive(1000);
assertNotNull("test message was consumed and rolled back, but is gone", result);
- assertEquals("1", ((TextMessage) result).getText());
- assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered());
-
- result = _consumer.receive(1000);
- assertNotNull("test message was consumed and rolled back, but is gone", result);
- assertEquals("2", ((TextMessage) result).getText());
- assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered());
-
+ if (result.getJMSRedelivered())
+ {
+ assertEquals("1", ((TextMessage) result).getText());
+
+ result = _consumer.receive(1000);
+ assertNotNull("test message was consumed and rolled back, but is gone", result);
+ assertEquals("2", ((TextMessage) result).getText());
+ assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered());
+ }
+ else
+ {
+ assertEquals("2", ((TextMessage) result).getText());
+ assertTrue("Messasge is marked as redelivered" + result, !result.getJMSRedelivered());
+
+ result = _consumer.receive(1000);
+ assertNotNull("test message was consumed and rolled back, but is gone", result);
+ assertEquals("1", ((TextMessage) result).getText());
+ assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered());
+
+ }
result = _consumer.receive(1000);
assertNull("test message should be null:" + result, result);
+
+ }
+
+
+ public void testPutThenRollbackThenGet() throws Exception
+ {
+ assertTrue("session is not transacted", _session.getTransacted());
+ assertTrue("session is not transacted", _pubSession.getTransacted());
+
+ _logger.info("sending test message");
+ String MESSAGE_TEXT = "testPutThenRollbackThenGet";
+
+ _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
+ _pubSession.commit();
+
+ assertNotNull(_consumer.receive(100));
+
+ _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
+
+ _logger.info("rolling back");
+ _pubSession.rollback();
+
+ _logger.info("receiving result");
+ Message result = _consumer.receive(1000);
+ assertNull("test message was put and rolled back, but is still present", result);
+
+ _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT));
+
+ _pubSession.commit();
+
+ assertNotNull(_consumer.receive(100));
+
}
}
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/testutil/Config.java b/qpid/java/client/src/test/java/org/apache/qpid/testutil/Config.java
index 8109d20a33..b777cf93b6 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/testutil/Config.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/testutil/Config.java
@@ -172,7 +172,7 @@ public class Config
}
catch(NumberFormatException e)
{
- throw new RuntimeException("Bad port number: " + value);
+ throw new RuntimeException("Bad port number: " + value, e);
}
}
else if("-name".equalsIgnoreCase(key))
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java b/qpid/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java
index f2afa472ab..195ed79dab 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java
@@ -3,6 +3,7 @@ package org.apache.qpid.testutil;
import org.apache.qpid.client.AMQConnectionFactory;
import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.JMSAMQException;
import org.apache.qpid.url.URLSyntaxException;
import org.apache.log4j.Logger;
@@ -70,7 +71,7 @@ public class QpidClientConnection implements ExceptionListener
}
catch (URLSyntaxException e)
{
- throw new JMSException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage());
+ throw new JMSAMQException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage(), e);
}
}
}
diff --git a/qpid/java/common/bin/qpid-run b/qpid/java/common/bin/qpid-run
index 6d7837c120..fe8fd0e9cc 100644
--- a/qpid/java/common/bin/qpid-run
+++ b/qpid/java/common/bin/qpid-run
@@ -106,15 +106,20 @@ usage() {
export EXTERNAL_CLASSPATH=$CLASSPATH
unset CLASSPATH
-conf=$QPID_HOME/etc/$program.conf
-if [ ! -e $conf ]; then
- conf=$QPID_HOME/etc/$(basename ${sourced}).conf
+#Use QPID_CLASSPATH if set
+if [ -n "$QPID_CLASSPATH" ]; then
+ export CLASSPATH=$QPID_CLASSPATH
+ echo "Using QPID_CLASSPATH" $QPID_CLASSPATH
+else
+ echo "Warning: Qpid classpath not set. CLASSPATH must include qpid jars."
fi
-if [ -r $conf ]; then
- . $conf
+#Use QPID_JAVA_MEM if set
+if [ -n "$QPID_JAVA_MEM" ]; then
+ export JAVA_MEM=$QPID_JAVA_MEM
+ echo "Using QPID_JAVA_MEM setting" $QPID_JAVA_MEM
else
- die "unable to source $conf"
+ echo "Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM" $JAVA_MEM
fi
declare -a RUN_ARGS JAVA_ARGS
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java b/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
index 0222fd9b4e..3e93243a1d 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
@@ -23,11 +23,41 @@ package org.apache.qpid;
import org.apache.log4j.Logger;
import org.apache.qpid.protocol.AMQConstant;
-/** Generic AMQ exception. */
+/**
+ * AMQException forms the root exception of all exceptions relating to the AMQ protocol. It provides space to associate
+ * an AMQ error code with the exception, which is a numberic value, with a meaning defined by the protocol.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Represents an exception condition associated with an AMQ protocol error code.
+ * </table>
+ *
+ * @todo This exception class is also used as a generic exception throughout Qpid code. This usage may not be strictly
+ * correct if this is to signify a protocol exception. Should review.
+ */
public class AMQException extends Exception
{
+ /** Holds the AMQ error code constant associated with this exception. */
private AMQConstant _errorCode;
+ /**
+ * Creates an exception with an optional error code, optional message and optional underlying cause.
+ *
+ * @param errorCode The error code. May be null if not to be set.
+ * @param msg The exception message. May be null if not to be set.
+ * @param t The underlying cause of the exception. May be null if not to be set.
+ */
+ public AMQException(AMQConstant errorCode, String msg, Throwable t)
+ {
+ super(((msg == null) ? "" : msg) + ((errorCode == null) ? "" : (" [error code " + errorCode + "]")), t);
+ _errorCode = errorCode;
+ }
+
+ /**
+ * @param message
+ *
+ * @deprecated Use {@link #AMQException(org.apache.qpid.protocol.AMQConstant, String, Throwable)} instead.
+ */
public AMQException(String message)
{
super(message);
@@ -35,6 +65,12 @@ public class AMQException extends Exception
_errorCode = AMQConstant.getConstant(-1);
}
+ /**
+ * @param msg
+ * @param t
+ *
+ * @deprecated Use {@link #AMQException(org.apache.qpid.protocol.AMQConstant, String, Throwable)} instead.
+ */
public AMQException(String msg, Throwable t)
{
super(msg, t);
@@ -42,18 +78,19 @@ public class AMQException extends Exception
_errorCode = AMQConstant.getConstant(-1);
}
- public AMQException(AMQConstant errorCode, String msg, Throwable t)
- {
- super(msg + " [error code " + errorCode + ']', t);
- _errorCode = errorCode;
- }
-
+ /**
+ * @param errorCode
+ * @param msg
+ *
+ * @deprecated Use {@link #AMQException(org.apache.qpid.protocol.AMQConstant, String, Throwable)} instead.
+ */
public AMQException(AMQConstant errorCode, String msg)
{
super(msg + " [error code " + errorCode + ']');
_errorCode = errorCode;
}
+ /*
public AMQException(Logger logger, String msg, Throwable t)
{
this(msg, t);
@@ -71,10 +108,15 @@ public class AMQException extends Exception
this(errorCode, msg);
logger.error(getMessage(), this);
}
+ */
+ /**
+ * Gets the AMQ protocol exception code associated with this exception.
+ *
+ * @return The AMQ protocol exception code associated with this exception.
+ */
public AMQConstant getErrorCode()
{
return _errorCode;
}
-
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/configuration/PropertyException.java b/qpid/java/common/src/main/java/org/apache/qpid/configuration/PropertyException.java
index 958f59191f..7c85a08e11 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/configuration/PropertyException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/configuration/PropertyException.java
@@ -1,3 +1,4 @@
+/* Copyright Rupert Smith, 2005 to 2006, all rights reserved. */
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -7,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,6 +22,7 @@
package org.apache.qpid.configuration;
import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
@@ -49,7 +51,7 @@ public class PropertyException extends AMQException
super(errorCode, msg);
}
- public PropertyException(Logger logger, String msg, Throwable t)
+ /*public PropertyException(Logger logger, String msg, Throwable t)
{
super(logger, msg, t);
}
@@ -62,5 +64,5 @@ public class PropertyException extends AMQException
public PropertyException(Logger logger, AMQConstant errorCode, String msg)
{
super(logger, errorCode, msg);
- }
+ }*/
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
index 43f888c029..9f36448986 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlockDecoder.java
@@ -94,7 +94,7 @@ public class AMQDataBlockDecoder
if(bodyFactory == null)
{
- throw new AMQFrameDecodingException("Unsupported frame type: " + type);
+ throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null);
}
final int channel = in.getUnsignedShort();
@@ -103,8 +103,8 @@ public class AMQDataBlockDecoder
// bodySize can be zero
if (channel < 0 || bodySize < 0)
{
- throw new AMQFrameDecodingException("Undecodable frame: type = " + type + " channel = " + channel +
- " bodySize = " + bodySize);
+ throw new AMQFrameDecodingException(null, "Undecodable frame: type = " + type + " channel = " + channel +
+ " bodySize = " + bodySize, null);
}
AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory);
@@ -113,7 +113,7 @@ public class AMQDataBlockDecoder
byte marker = in.get();
if ((marker & 0xFF) != 0xCE)
{
- throw new AMQFrameDecodingException("End of frame marker not found. Read " + marker + " length=" + bodySize + " type=" + type);
+ throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize + " type=" + type, null);
}
return frame;
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrameDecodingException.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrameDecodingException.java
index a24bd6aaa9..c462dec2a3 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrameDecodingException.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrameDecodingException.java
@@ -1,3 +1,4 @@
+/* Copyright Rupert Smith, 2005 to 2006, all rights reserved. */
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -7,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -21,21 +22,23 @@
package org.apache.qpid.framing;
import org.apache.log4j.Logger;
+
import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
public class AMQFrameDecodingException extends AMQException
{
- public AMQFrameDecodingException(String message)
+ /*public AMQFrameDecodingException(String message)
{
super(message);
- }
+ }*/
- public AMQFrameDecodingException(String message, Throwable t)
+ public AMQFrameDecodingException(AMQConstant errorCode, String message, Throwable t)
{
- super(message, t);
+ super(errorCode, message, t);
}
- public AMQFrameDecodingException(Logger log, String message)
+ /*public AMQFrameDecodingException(Logger log, String message)
{
super(log, message);
}
@@ -43,6 +46,5 @@ public class AMQFrameDecodingException extends AMQException
public AMQFrameDecodingException(Logger log, String message, Throwable t)
{
super(log, message, t);
- }
-
+ }*/
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
index f51296dafc..f2492585bc 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
@@ -9,7 +9,7 @@ import org.apache.mina.common.ByteBuffer;
* and thus can be held more effectively in a byte buffer.
*
*/
-public final class AMQShortString implements CharSequence
+public final class AMQShortString implements CharSequence, Comparable<AMQShortString>
{
private static final Logger _logger = Logger.getLogger(AMQShortString.class);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
index 8b784fa3f7..008afb490e 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
@@ -341,7 +341,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
}
catch (AMQFrameDecodingException e)
{
- throw new RuntimeException("Error in content header data: " + e);
+ throw new RuntimeException("Error in content header data: " + e, e);
}
final int endPos = buffer.position();
@@ -381,7 +381,7 @@ public class BasicContentHeaderProperties implements CommonContentHeaderProperti
}
catch (AMQFrameDecodingException e)
{
- throw new RuntimeException("Error in content header data: " + e);
+ throw new RuntimeException("Error in content header data: " + e, e);
}
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
index 7dac018872..712eb437db 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderPropertiesFactory.java
@@ -49,7 +49,7 @@ public class ContentHeaderPropertiesFactory
}
else
{
- throw new AMQFrameDecodingException("Unsupport content header class id: " + classId);
+ throw new AMQFrameDecodingException(null, "Unsupport content header class id: " + classId, null);
}
properties.populatePropertiesFromBuffer(buffer, propertyFlags, size);
return properties;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
index f94cd4934c..f0cdda487c 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,6 +23,7 @@ package org.apache.qpid.framing;
import java.nio.charset.Charset;
import org.apache.log4j.Logger;
+
import org.apache.mina.common.ByteBuffer;
public class EncodingUtils
@@ -49,96 +50,95 @@ public class EncodingUtils
}
}
-
public static int encodedShortStringLength(short s)
{
- if( s == 0 )
+ if (s == 0)
{
return 1 + 1;
}
int len = 0;
- if(s < 0)
+ if (s < 0)
{
- len=1;
+ len = 1;
// sloppy - doesn't work of Integer.MIN_VALUE
- s=(short)-s;
+ s = (short) -s;
}
- if(s>9999)
+ if (s > 9999)
{
- return 1+5;
+ return 1 + 5;
}
- else if(s>999)
+ else if (s > 999)
{
- return 1+4;
+ return 1 + 4;
}
- else if(s>99)
+ else if (s > 99)
{
- return 1+3;
+ return 1 + 3;
}
- else if(s>9)
+ else if (s > 9)
{
- return 1+2;
+ return 1 + 2;
}
else
{
- return 1+1;
+ return 1 + 1;
}
}
-
public static int encodedShortStringLength(int i)
{
- if( i == 0 )
+ if (i == 0)
{
return 1 + 1;
}
int len = 0;
- if(i < 0)
+ if (i < 0)
{
- len=1;
+ len = 1;
// sloppy - doesn't work of Integer.MIN_VALUE
- i=-i;
+ i = -i;
}
// range is now 1 - 2147483647
- if(i < Short.MAX_VALUE)
+ if (i < Short.MAX_VALUE)
{
- return len + encodedShortStringLength((short)i);
+ return len + encodedShortStringLength((short) i);
}
else if (i > 999999)
{
- return len + 6 + encodedShortStringLength((short)(i/1000000));
+ return len + 6 + encodedShortStringLength((short) (i / 1000000));
}
else // if (i > 99999)
{
- return len + 5 + encodedShortStringLength((short)(i/100000));
+ return len + 5 + encodedShortStringLength((short) (i / 100000));
}
}
public static int encodedShortStringLength(long l)
{
- if(l == 0)
+ if (l == 0)
{
return 1 + 1;
}
int len = 0;
- if(l < 0)
+ if (l < 0)
{
- len=1;
+ len = 1;
// sloppy - doesn't work of Long.MIN_VALUE
- l=-l;
+ l = -l;
}
- if(l < Integer.MAX_VALUE)
+
+ if (l < Integer.MAX_VALUE)
{
return len + encodedShortStringLength((int) l);
}
- else if(l > 9999999999L)
+ else if (l > 9999999999L)
{
return len + 10 + encodedShortStringLength((int) (l / 10000000000L));
}
@@ -149,7 +149,6 @@ public class EncodingUtils
}
-
public static int encodedShortStringLength(AMQShortString s)
{
if (s == null)
@@ -162,7 +161,6 @@ public class EncodingUtils
}
}
-
public static int encodedLongStringLength(String s)
{
if (s == null)
@@ -219,7 +217,6 @@ public class EncodingUtils
return 0;
}
-
public static void writeShortStringBytes(ByteBuffer buffer, String s)
{
if (s != null)
@@ -230,6 +227,7 @@ public class EncodingUtils
{
encodedString[i] = (byte) cha[i];
}
+
writeBytes(buffer, encodedString);
}
else
@@ -239,7 +237,6 @@ public class EncodingUtils
}
}
-
public static void writeShortStringBytes(ByteBuffer buffer, AMQShortString s)
{
if (s != null)
@@ -256,7 +253,7 @@ public class EncodingUtils
public static void writeLongStringBytes(ByteBuffer buffer, String s)
{
- assert s == null || s.length() <= 0xFFFE;
+ assert (s == null) || (s.length() <= 0xFFFE);
if (s != null)
{
int len = s.length();
@@ -267,6 +264,7 @@ public class EncodingUtils
{
encodedString[i] = (byte) cha[i];
}
+
buffer.put(encodedString);
}
else
@@ -277,7 +275,7 @@ public class EncodingUtils
public static void writeLongStringBytes(ByteBuffer buffer, char[] s)
{
- assert s == null || s.length <= 0xFFFE;
+ assert (s == null) || (s.length <= 0xFFFE);
if (s != null)
{
int len = s.length;
@@ -287,6 +285,7 @@ public class EncodingUtils
{
encodedString[i] = (byte) s[i];
}
+
buffer.put(encodedString);
}
else
@@ -297,7 +296,7 @@ public class EncodingUtils
public static void writeLongStringBytes(ByteBuffer buffer, byte[] bytes)
{
- assert bytes == null || bytes.length <= 0xFFFE;
+ assert (bytes == null) || (bytes.length <= 0xFFFE);
if (bytes != null)
{
writeUnsignedInteger(buffer, bytes.length);
@@ -330,7 +329,6 @@ public class EncodingUtils
}
}
-
public static int unsignedIntegerLength()
{
return 4;
@@ -356,7 +354,6 @@ public class EncodingUtils
}
}
-
public static void writeFieldTableBytes(ByteBuffer buffer, FieldTable table)
{
if (table != null)
@@ -400,10 +397,9 @@ public class EncodingUtils
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
-
buffer.put(packedValue);
}
@@ -413,213 +409,181 @@ public class EncodingUtils
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
-
buffer.put(packedValue);
}
-
-
- public static void writeBooleans(ByteBuffer buffer,
- boolean value0,
- boolean value1,
- boolean value2,
- boolean value3)
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
if (value3)
{
- packedValue = (byte) (packedValue | (byte)(1 << 3));
+ packedValue = (byte) (packedValue | (byte) (1 << 3));
}
buffer.put(packedValue);
}
- public static void writeBooleans(ByteBuffer buffer,
- boolean value0,
- boolean value1,
- boolean value2,
- boolean value3,
- boolean value4)
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
if (value3)
{
- packedValue = (byte) (packedValue | (byte)(1 << 3));
+ packedValue = (byte) (packedValue | (byte) (1 << 3));
}
if (value4)
{
- packedValue = (byte) (packedValue | (byte)(1 << 4));
+ packedValue = (byte) (packedValue | (byte) (1 << 4));
}
buffer.put(packedValue);
}
- public static void writeBooleans(ByteBuffer buffer,
- boolean value0,
- boolean value1,
- boolean value2,
- boolean value3,
- boolean value4,
- boolean value5)
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
if (value3)
{
- packedValue = (byte) (packedValue | (byte)(1 << 3));
+ packedValue = (byte) (packedValue | (byte) (1 << 3));
}
if (value4)
{
- packedValue = (byte) (packedValue | (byte)(1 << 4));
+ packedValue = (byte) (packedValue | (byte) (1 << 4));
}
if (value5)
{
- packedValue = (byte) (packedValue | (byte)(1 << 5));
+ packedValue = (byte) (packedValue | (byte) (1 << 5));
}
buffer.put(packedValue);
}
- public static void writeBooleans(ByteBuffer buffer,
- boolean value0,
- boolean value1,
- boolean value2,
- boolean value3,
- boolean value4,
- boolean value5,
- boolean value6)
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5, boolean value6)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
if (value3)
{
- packedValue = (byte) (packedValue | (byte)(1 << 3));
+ packedValue = (byte) (packedValue | (byte) (1 << 3));
}
if (value4)
{
- packedValue = (byte) (packedValue | (byte)(1 << 4));
+ packedValue = (byte) (packedValue | (byte) (1 << 4));
}
if (value5)
{
- packedValue = (byte) (packedValue | (byte)(1 << 5));
+ packedValue = (byte) (packedValue | (byte) (1 << 5));
}
if (value6)
{
- packedValue = (byte) (packedValue | (byte)(1 << 6));
+ packedValue = (byte) (packedValue | (byte) (1 << 6));
}
buffer.put(packedValue);
}
- public static void writeBooleans(ByteBuffer buffer,
- boolean value0,
- boolean value1,
- boolean value2,
- boolean value3,
- boolean value4,
- boolean value5,
- boolean value6,
- boolean value7)
+ public static void writeBooleans(ByteBuffer buffer, boolean value0, boolean value1, boolean value2, boolean value3,
+ boolean value4, boolean value5, boolean value6, boolean value7)
{
byte packedValue = value0 ? (byte) 1 : (byte) 0;
if (value1)
{
- packedValue = (byte) (packedValue | (byte)(1 << 1));
+ packedValue = (byte) (packedValue | (byte) (1 << 1));
}
if (value2)
{
- packedValue = (byte) (packedValue | (byte)(1 << 2));
+ packedValue = (byte) (packedValue | (byte) (1 << 2));
}
if (value3)
{
- packedValue = (byte) (packedValue | (byte)(1 << 3));
+ packedValue = (byte) (packedValue | (byte) (1 << 3));
}
if (value4)
{
- packedValue = (byte) (packedValue | (byte)(1 << 4));
+ packedValue = (byte) (packedValue | (byte) (1 << 4));
}
if (value5)
{
- packedValue = (byte) (packedValue | (byte)(1 << 5));
+ packedValue = (byte) (packedValue | (byte) (1 << 5));
}
if (value6)
{
- packedValue = (byte) (packedValue | (byte)(1 << 6));
+ packedValue = (byte) (packedValue | (byte) (1 << 6));
}
if (value7)
{
- packedValue = (byte) (packedValue | (byte)(1 << 7));
+ packedValue = (byte) (packedValue | (byte) (1 << 7));
}
buffer.put(packedValue);
}
-
-
-
/**
* This is used for writing longstrs.
*
@@ -647,26 +611,27 @@ public class EncodingUtils
public static boolean[] readBooleans(ByteBuffer buffer)
{
final byte packedValue = buffer.get();
- if(packedValue == 0)
+ if (packedValue == 0)
{
return ALL_FALSE_ARRAY;
}
+
final boolean[] result = new boolean[8];
result[0] = ((packedValue & 1) != 0);
result[1] = ((packedValue & (1 << 1)) != 0);
result[2] = ((packedValue & (1 << 2)) != 0);
result[3] = ((packedValue & (1 << 3)) != 0);
- if((packedValue & 0xF0) == 0)
+ if ((packedValue & 0xF0) == 0)
{
result[0] = ((packedValue & 1) != 0);
}
+
result[4] = ((packedValue & (1 << 4)) != 0);
result[5] = ((packedValue & (1 << 5)) != 0);
result[6] = ((packedValue & (1 << 6)) != 0);
result[7] = ((packedValue & (1 << 7)) != 0);
-
return result;
}
@@ -742,6 +707,7 @@ public class EncodingUtils
{
stringChars[i] = (char) stringBytes[i];
}
+
return new String(stringChars);
}
}
@@ -757,6 +723,7 @@ public class EncodingUtils
{
byte[] result = new byte[(int) length];
buffer.get(result);
+
return result;
}
}
@@ -764,15 +731,14 @@ public class EncodingUtils
public static long readTimestamp(ByteBuffer buffer)
{
// Discard msb from AMQ timestamp
- //buffer.getUnsignedInt();
+ // buffer.getUnsignedInt();
return buffer.getLong();
}
-
static byte[] hexToByteArray(String id)
{
// Should check param for null, long enough for this check, upper-case and trailing char
- String s = (id.charAt(1) == 'x') ? id.substring(2) : id; // strip 0x
+ String s = (id.charAt(1) == 'x') ? id.substring(2) : id; // strip 0x
int len = s.length();
int byte_len = len / 2;
@@ -786,7 +752,7 @@ public class EncodingUtils
byte b1 = Byte.parseByte(s.substring(ch, ch + 1), 16);
byte b2 = Byte.parseByte(s.substring(ch + 1, ch + 2), 16);
- b[i] = (byte) (b1 * 16 + b2);
+ b[i] = (byte) ((b1 * 16) + b2);
}
return (b);
@@ -795,7 +761,7 @@ public class EncodingUtils
public static char[] convertToHexCharArray(byte[] from)
{
int length = from.length;
- char[] result_buff = new char[length * 2 + 2];
+ char[] result_buff = new char[(length * 2) + 2];
result_buff[0] = '0';
result_buff[1] = 'x';
@@ -831,7 +797,7 @@ public class EncodingUtils
byte[] from = new byte[size];
// Is this not the same.
- //bb.get(from, 0, length);
+ // bb.get(from, 0, length);
for (int i = 0; i < size; i++)
{
from[i] = bb.get(i);
@@ -840,9 +806,9 @@ public class EncodingUtils
return (new String(convertToHexCharArray(from)));
}
- private static char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ private static char[] hex_chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- //**** new methods
+ // **** new methods
// AMQP_BOOLEAN_PROPERTY_PREFIX
@@ -854,6 +820,7 @@ public class EncodingUtils
public static boolean readBoolean(ByteBuffer buffer)
{
byte packedValue = buffer.get();
+
return (packedValue == 1);
}
@@ -878,7 +845,6 @@ public class EncodingUtils
return 1;
}
-
// AMQP_SHORT_PROPERTY_PREFIX
public static void writeShort(ByteBuffer buffer, Short aShort)
{
@@ -943,7 +909,6 @@ public class EncodingUtils
return 4;
}
-
// Double_PROPERTY_PREFIX
public static void writeDouble(ByteBuffer buffer, Double aDouble)
{
@@ -960,7 +925,6 @@ public class EncodingUtils
return 8;
}
-
public static byte[] readBytes(ByteBuffer buffer)
{
short length = buffer.getUnsigned();
@@ -981,7 +945,7 @@ public class EncodingUtils
{
if (data != null)
{
- // TODO: check length fits in an unsigned byte
+ // TODO: check length fits in an unsigned byte
writeUnsignedByte(buffer, (short) data.length);
buffer.put(data);
}
@@ -992,7 +956,7 @@ public class EncodingUtils
}
}
- //CHAR_PROPERTY
+ // CHAR_PROPERTY
public static int encodedCharLength()
{
return encodedByteLength();
@@ -1000,31 +964,29 @@ public class EncodingUtils
public static char readChar(ByteBuffer buffer)
{
- //This is valid as we know that the Character is ASCII 0..127
+ // This is valid as we know that the Character is ASCII 0..127
return (char) buffer.get();
}
public static void writeChar(ByteBuffer buffer, char character)
{
- //This is valid as we know that the Character is ASCII 0..127
+ // This is valid as we know that the Character is ASCII 0..127
writeByte(buffer, (byte) character);
}
-
-
-
public static long readLongAsShortString(ByteBuffer buffer)
{
short length = buffer.getUnsigned();
short pos = 0;
- if(length == 0)
+ if (length == 0)
{
return 0L;
}
+
byte digit = buffer.get();
boolean isNegative;
long result = 0;
- if(digit == (byte)'-')
+ if (digit == (byte) '-')
{
isNegative = true;
pos++;
@@ -1034,15 +996,16 @@ public class EncodingUtils
{
isNegative = false;
}
- result = digit - (byte)'0';
+
+ result = digit - (byte) '0';
pos++;
- while(pos < length)
+ while (pos < length)
{
pos++;
digit = buffer.get();
result = (result << 3) + (result << 1);
- result += digit - (byte)'0';
+ result += digit - (byte) '0';
}
return result;
@@ -1051,33 +1014,13 @@ public class EncodingUtils
public static long readUnsignedInteger(ByteBuffer buffer)
{
long l = 0xFF & buffer.get();
- l <<=8;
+ l <<= 8;
l = l | (0xFF & buffer.get());
- l <<=8;
+ l <<= 8;
l = l | (0xFF & buffer.get());
- l <<=8;
+ l <<= 8;
l = l | (0xFF & buffer.get());
return l;
}
-
-
- public static void main(String[] args)
- {
- ByteBuffer buf = ByteBuffer.allocate(8);
- buf.setAutoExpand(true);
-
- long l = (long) Integer.MAX_VALUE;
- l += 1024L;
-
- writeUnsignedInteger(buf, l);
-
- buf.flip();
-
- long l2 = readUnsignedInteger(buf);
-
- System.out.println("before: " + l);
- System.out.println("after: " + l2);
- }
-
}
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 ec371453aa..faa7cc1e82 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
@@ -148,34 +148,30 @@ public class VersionSpecificRegistry
}
catch(NullPointerException e)
{
- throw new AMQFrameDecodingException(_log,
- "Class " + classID + " unknown in AMQP version " + _protocolMajorVersion + "-" + _protocolMinorVersion
- + " (while trying to decode class " + classID + " method " + methodID + ".");
+ 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(_log,
- "Class " + classID + " unknown in AMQP version " + _protocolMajorVersion + "-" + _protocolMinorVersion
- + " (while trying to decode class " + classID + " method " + methodID + ".");
-
+ 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(_log,
- "Method " + methodID + " unknown in AMQP version " + _protocolMajorVersion + "-" + _protocolMinorVersion
- + " (while trying to decode class " + classID + " method " + methodID + ".");
-
+ 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(_log,
- "Method " + methodID + " unknown in AMQP version " + _protocolMajorVersion + "-" + _protocolMinorVersion
- + " (while trying to decode class " + classID + " method " + methodID + ".");
+ throw new AMQFrameDecodingException(null, "Method " + methodID + " unknown in AMQP version " + _protocolMajorVersion
+ + "-" + _protocolMinorVersion + " (while trying to decode class " + classID + " method " + methodID + ".", null);
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java
index 09890a103d..7300ec8c3f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/Event.java
@@ -85,4 +85,27 @@ abstract public class Event
}
+
+ public static final class CloseEvent extends Event
+ {
+ private final IoFilter.NextFilter _nextFilter;
+
+ public CloseEvent(final IoFilter.NextFilter nextFilter)
+ {
+ super();
+ _nextFilter = nextFilter;
+ }
+
+
+ public void process(IoSession session)
+ {
+ _nextFilter.sessionClosed(session);
+ }
+
+ public IoFilter.NextFilter getNextFilter()
+ {
+ return _nextFilter;
+ }
+ }
+
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
index 8126ca4bc8..c9c96925cb 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -24,10 +24,13 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.log4j.Logger;
+
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoFilterAdapter;
import org.apache.mina.common.IoSession;
+import org.apache.qpid.pool.Event.CloseEvent;
+
public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionHandler
{
private static final Logger _logger = Logger.getLogger(PoolingFilter.class);
@@ -47,12 +50,12 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
void fireAsynchEvent(IoSession session, Event event)
{
Job job = getJobForSession(session);
- // job.acquire(); //prevents this job being removed from _jobs
+ // job.acquire(); //prevents this job being removed from _jobs
job.add(event);
- //Additional checks on pool to check that it hasn't shutdown.
+ // Additional checks on pool to check that it hasn't shutdown.
// The alternative is to catch the RejectedExecutionException that will result from executing on a shutdown pool
- if (job.activate() && _poolReference.getPool() != null && !_poolReference.getPool().isShutdown())
+ if (job.activate() && (_poolReference.getPool() != null) && !_poolReference.getPool().isShutdown())
{
_poolReference.getPool().execute(job);
}
@@ -68,16 +71,6 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
private Job getJobForSession(IoSession session)
{
return (Job) session.getAttribute(_name);
-
-/* if(job == null)
- {
- System.err.println("Error in " + _name);
- Thread.dumpStack();
- }
-
-
- job = _jobs.get(session);
- return job == null ? createJobForSession(session) : job;*/
}
private Job createJobForSession(IoSession session)
@@ -87,35 +80,36 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
private Job addJobForSession(IoSession session, Job job)
{
- //atomic so ensures all threads agree on the same job
+ // atomic so ensures all threads agree on the same job
Job existing = _jobs.putIfAbsent(session, job);
- return existing == null ? job : existing;
+
+ return (existing == null) ? job : existing;
}
- //Job.JobCompletionHandler
+ // Job.JobCompletionHandler
public void completed(IoSession session, Job job)
{
-// if (job.isComplete())
-// {
-// job.release();
-// if (!job.isReferenced())
-// {
-// _jobs.remove(session);
-// }
-// }
-// else
- if(!job.isComplete())
+ // if (job.isComplete())
+ // {
+ // job.release();
+ // if (!job.isReferenced())
+ // {
+ // _jobs.remove(session);
+ // }
+ // }
+ // else
+ if (!job.isComplete())
{
// ritchiem : 2006-12-13 Do we need to perform the additional checks here?
- // Can the pool be shutdown at this point?
- if (job.activate() && _poolReference.getPool() != null && !_poolReference.getPool().isShutdown())
+ // Can the pool be shutdown at this point?
+ if (job.activate() && (_poolReference.getPool() != null) && !_poolReference.getPool().isShutdown())
{
_poolReference.getPool().execute(job);
}
}
}
- //IoFilter methods that are processed by threads on the pool
+ // IoFilter methods that are processed by threads on the pool
public void sessionOpened(final NextFilter nextFilter, final IoSession session) throws Exception
{
@@ -127,37 +121,33 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
nextFilter.sessionClosed(session);
}
- public void sessionIdle(final NextFilter nextFilter, final IoSession session,
- final IdleStatus status) throws Exception
+ public void sessionIdle(final NextFilter nextFilter, final IoSession session, final IdleStatus status) throws Exception
{
nextFilter.sessionIdle(session, status);
}
- public void exceptionCaught(final NextFilter nextFilter, final IoSession session,
- final Throwable cause) throws Exception
+ public void exceptionCaught(final NextFilter nextFilter, final IoSession session, final Throwable cause) throws Exception
{
- nextFilter.exceptionCaught(session,cause);
+ nextFilter.exceptionCaught(session, cause);
}
- public void messageReceived(final NextFilter nextFilter, final IoSession session,
- final Object message) throws Exception
+ public void messageReceived(final NextFilter nextFilter, final IoSession session, final Object message) throws Exception
{
- nextFilter.messageReceived(session,message);
+ nextFilter.messageReceived(session, message);
}
- public void messageSent(final NextFilter nextFilter, final IoSession session,
- final Object message) throws Exception
+ public void messageSent(final NextFilter nextFilter, final IoSession session, final Object message) throws Exception
{
nextFilter.messageSent(session, message);
}
- public void filterWrite(final NextFilter nextFilter, final IoSession session,
- final WriteRequest writeRequest) throws Exception
+ public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest)
+ throws Exception
{
nextFilter.filterWrite(session, writeRequest);
}
- //IoFilter methods that are processed on current thread (NOT on pooled thread)
+ // IoFilter methods that are processed on current thread (NOT on pooled thread)
public void filterClose(NextFilter nextFilter, IoSession session) throws Exception
{
@@ -199,13 +189,17 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
super(refCountingPool, name);
}
- public void messageReceived(final NextFilter nextFilter, final IoSession session,
- final Object message) throws Exception
+ public void messageReceived(final NextFilter nextFilter, final IoSession session, final Object message)
+ throws Exception
{
fireAsynchEvent(session, new Event.ReceivedEvent(nextFilter, message));
}
+ public void sessionClosed(final NextFilter nextFilter, final IoSession session) throws Exception
+ {
+ fireAsynchEvent(session, new CloseEvent(nextFilter));
+ }
}
@@ -217,26 +211,27 @@ public class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionH
super(refCountingPool, name);
}
-
- public void filterWrite(final NextFilter nextFilter, final IoSession session,
- final WriteRequest writeRequest) throws Exception
+ public void filterWrite(final NextFilter nextFilter, final IoSession session, final WriteRequest writeRequest)
+ throws Exception
{
fireAsynchEvent(session, new Event.WriteEvent(nextFilter, writeRequest));
}
+ public void sessionClosed(final NextFilter nextFilter, final IoSession session) throws Exception
+ {
+ fireAsynchEvent(session, new CloseEvent(nextFilter));
+ }
+
}
- public static PoolingFilter createAynschReadPoolingFilter(ReferenceCountingExecutorService refCountingPool,String name)
+ public static PoolingFilter createAynschReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- return new AsynchReadPoolingFilter(refCountingPool,name);
+ return new AsynchReadPoolingFilter(refCountingPool, name);
}
-
- public static PoolingFilter createAynschWritePoolingFilter(ReferenceCountingExecutorService refCountingPool,String name)
+ public static PoolingFilter createAynschWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name)
{
- return new AsynchWritePoolingFilter(refCountingPool,name);
+ return new AsynchWritePoolingFilter(refCountingPool, name);
}
}
-
-
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java b/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java
index f558523864..353c0d39c2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -24,9 +24,10 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
+import org.apache.log4j.Logger;
+
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
-import org.apache.log4j.Logger;
public class AMQBindingURL implements BindingURL
{
@@ -39,10 +40,9 @@ public class AMQBindingURL implements BindingURL
AMQShortString _queueName;
private HashMap<String, String> _options;
-
public AMQBindingURL(String url) throws URLSyntaxException
{
- //format:
+ // format:
// <exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']*
_logger.debug("Parsing URL: " + url);
_url = url;
@@ -61,10 +61,10 @@ public class AMQBindingURL implements BindingURL
if (exchangeClass == null)
{
- _url = ExchangeDefaults.DIRECT_EXCHANGE_CLASS + "://" +
- "" + "//" + _url;
- //URLHelper.parseError(-1, "Exchange Class not specified.", _url);
+ _url = ExchangeDefaults.DIRECT_EXCHANGE_CLASS + "://" + "" + "//" + _url;
+ // URLHelper.parseError(-1, "Exchange Class not specified.", _url);
parseBindingURL();
+
return;
}
else
@@ -76,7 +76,7 @@ public class AMQBindingURL implements BindingURL
if (exchangeName == null)
{
- if(getExchangeClass().equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))
+ if (getExchangeClass().equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))
{
setExchangeName("");
}
@@ -92,11 +92,10 @@ public class AMQBindingURL implements BindingURL
String queueName;
- if (connection.getPath() == null ||
- connection.getPath().equals(""))
+ if ((connection.getPath() == null) || connection.getPath().equals(""))
{
throw URLHelper.parseError(_url.indexOf(_exchangeName.toString()) + _exchangeName.length(),
- "Destination or Queue requried", _url);
+ "Destination or Queue requried", _url);
}
else
{
@@ -104,7 +103,7 @@ public class AMQBindingURL implements BindingURL
if (slash == -1)
{
throw URLHelper.parseError(_url.indexOf(_exchangeName.toString()) + _exchangeName.length(),
- "Destination requried", _url);
+ "Destination requried", _url);
}
else
{
@@ -127,9 +126,8 @@ public class AMQBindingURL implements BindingURL
setQueueName(queueName);
- //Fragment is #string (not used)
- //System.out.println(connection.getFragment());
- _logger.debug("URL Parsed: " + this);
+ // Fragment is #string (not used)
+ _logger.debug("URL Parsed: " + this);
}
catch (URISyntaxException uris)
@@ -162,7 +160,7 @@ public class AMQBindingURL implements BindingURL
private void processOptions()
{
- //this is where we would parse any options that needed more than just storage.
+ // this is where we would parse any options that needed more than just storage.
}
public String getURL()
@@ -219,11 +217,13 @@ public class AMQBindingURL implements BindingURL
{
if (containsOption(BindingURL.OPTION_CLIENTID) && containsOption(BindingURL.OPTION_SUBSCRIPTION))
{
- _queueName = new AMQShortString(getOption(BindingURL.OPTION_CLIENTID + ":" + BindingURL.OPTION_SUBSCRIPTION));
+ _queueName =
+ new AMQShortString(getOption(BindingURL.OPTION_CLIENTID + ":" + BindingURL.OPTION_SUBSCRIPTION));
}
else
{
- throw URLHelper.parseError(-1, "Durable subscription must have values for " + BindingURL.OPTION_CLIENTID + " and " + BindingURL.OPTION_SUBSCRIPTION + ".", _url);
+ throw URLHelper.parseError(-1, "Durable subscription must have values for " + BindingURL.OPTION_CLIENTID
+ + " and " + BindingURL.OPTION_SUBSCRIPTION + ".", _url);
}
}
@@ -237,7 +237,6 @@ public class AMQBindingURL implements BindingURL
_queueName = name;
}
-
}
public String getOption(String key)
@@ -275,7 +274,6 @@ public class AMQBindingURL implements BindingURL
setOption(OPTION_ROUTING_KEY, key.toString());
}
-
public String toString()
{
StringBuffer sb = new StringBuffer();
@@ -289,18 +287,7 @@ public class AMQBindingURL implements BindingURL
sb.append(_queueName);
sb.append(URLHelper.printOptions(_options));
- return sb.toString();
- }
-
- public static void main(String args[]) throws URLSyntaxException
- {
- String url = "exchangeClass://exchangeName/Destination/Queue?option='value',option2='value2'";
-
- AMQBindingURL dest = new AMQBindingURL(url);
-
- System.out.println(url);
- System.out.println(dest);
+ return sb.toString();
}
-
}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/url/URLHelper.java b/qpid/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
index 806f879818..c08b443acf 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
@@ -7,9 +7,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -30,10 +30,10 @@ public class URLHelper
public static void parseOptions(HashMap<String, String> optionMap, String options) throws URLSyntaxException
{
- //options looks like this
- //brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value''
+ // options looks like this
+ // brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value''
- if (options == null || options.indexOf('=') == -1)
+ if ((options == null) || (options.indexOf('=') == -1))
{
return;
}
@@ -49,8 +49,8 @@ public class URLHelper
// to store index of final "'"
int valueIndex = optionIndex;
- //Walk remainder of url.
- while (nestedQuotes > 0 || valueIndex < length)
+ // Walk remainder of url.
+ while ((nestedQuotes > 0) || (valueIndex < length))
{
valueIndex++;
@@ -61,27 +61,24 @@ public class URLHelper
if (options.charAt(valueIndex) == '\'')
{
- if (valueIndex + 1 < options.length())
+ if ((valueIndex + 1) < options.length())
{
- if (options.charAt(valueIndex + 1) == DEFAULT_OPTION_SEPERATOR ||
- options.charAt(valueIndex + 1) == ALTERNATIVE_OPTION_SEPARATOR ||
- options.charAt(valueIndex + 1) == BROKER_SEPARATOR ||
- options.charAt(valueIndex + 1) == '\'')
+ if ((options.charAt(valueIndex + 1) == DEFAULT_OPTION_SEPERATOR)
+ || (options.charAt(valueIndex + 1) == ALTERNATIVE_OPTION_SEPARATOR)
+ || (options.charAt(valueIndex + 1) == BROKER_SEPARATOR)
+ || (options.charAt(valueIndex + 1) == '\''))
{
nestedQuotes--;
-// System.out.println(
-// options + "\n" + "-" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1));
+
if (nestedQuotes == 0)
{
- //We've found the value of an option
+ // We've found the value of an option
break;
}
}
else
{
nestedQuotes++;
-// System.out.println(
-// options + "\n" + "+" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1));
}
}
else
@@ -98,11 +95,11 @@ public class URLHelper
}
}
- if (nestedQuotes != 0 || valueIndex < (optionIndex + 2))
+ if ((nestedQuotes != 0) || (valueIndex < (optionIndex + 2)))
{
int sepIndex = 0;
- //Try and identify illegal separator character
+ // Try and identify illegal separator character
if (nestedQuotes > 1)
{
for (int i = 0; i < nestedQuotes; i++)
@@ -112,14 +109,14 @@ public class URLHelper
}
}
- if (sepIndex >= options.length() || sepIndex == 0)
+ if ((sepIndex >= options.length()) || (sepIndex == 0))
{
throw parseError(valueIndex, "Unterminated option", options);
}
else
{
- throw parseError(sepIndex, "Unterminated option. Possible illegal option separator:'" +
- options.charAt(sepIndex) + "'", options);
+ throw parseError(sepIndex, "Unterminated option. Possible illegal option separator:'"
+ + options.charAt(sepIndex) + "'", options);
}
}
@@ -130,12 +127,11 @@ public class URLHelper
if (valueIndex < (options.length() - 1))
{
- //Recurse to get remaining options
+ // Recurse to get remaining options
parseOptions(optionMap, options.substring(valueIndex + 2));
}
}
-
public static URLSyntaxException parseError(int index, String error, String url)
{
return parseError(index, 1, error, url);
diff --git a/qpid/java/distribution/src/main/assembly/bin.xml b/qpid/java/distribution/src/main/assembly/bin.xml
index 0d4146ed1d..ef85137f90 100644
--- a/qpid/java/distribution/src/main/assembly/bin.xml
+++ b/qpid/java/distribution/src/main/assembly/bin.xml
@@ -83,6 +83,24 @@
<fileMode>420</fileMode>
</file>
<file>
+ <source>../broker/etc/jmxremote.access</source>
+ <outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
+ <destName>jmxremote.access</destName>
+ <fileMode>420</fileMode>
+ </file>
+ <file>
+ <source>../broker/etc/transient_config.xml</source>
+ <outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
+ <destName>transient_config.xml</destName>
+ <fileMode>420</fileMode>
+ </file>
+ <file>
+ <source>../broker/etc/persistent_config.xml</source>
+ <outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
+ <destName>persistent_config.xml</destName>
+ <fileMode>420</fileMode>
+ </file>
+ <file>
<source>../broker/etc/log4j.xml</source>
<outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
<destName>log4j.xml</destName>
@@ -113,6 +131,18 @@
<fileMode>420</fileMode>
</file>
<file>
+ <source>../broker/bin/qpid.stop</source>
+ <outputDirectory>qpid-${qpid.version}/bin</outputDirectory>
+ <destName>qpid.stop</destName>
+ <fileMode>493</fileMode>
+ </file>
+ <file>
+ <source>../broker/bin/qpid.stopall</source>
+ <outputDirectory>qpid-${qpid.version}/bin</outputDirectory>
+ <destName>qpid.stopall</destName>
+ <fileMode>493</fileMode>
+ </file>
+ <file>
<source>../common/bin/qpid-run</source>
<outputDirectory>qpid-${qpid.version}/bin</outputDirectory>
<destName>qpid-run</destName>
diff --git a/qpid/java/distribution/src/main/assembly/management-eclipse-plugin.xml b/qpid/java/distribution/src/main/assembly/management-eclipse-plugin.xml
index 5d89c55968..98534d43d0 100644
--- a/qpid/java/distribution/src/main/assembly/management-eclipse-plugin.xml
+++ b/qpid/java/distribution/src/main/assembly/management-eclipse-plugin.xml
@@ -88,6 +88,13 @@
</includes>
<fileMode>777</fileMode>
</fileSet>
+ <fileSet>
+ <directory>../management/eclipse-plugin/src/main/resources/sasl</directory>
+ <outputDirectory>qpidmc/eclipse/plugins/jmxremote.optional_1.0.1/META-INF</outputDirectory>
+ <includes>
+ <include>MANIFEST.MF</include>
+ </includes>
+ </fileSet>
</fileSets>
<dependencySets>
diff --git a/qpid/java/management/eclipse-plugin/META-INF/MANIFEST.MF b/qpid/java/management/eclipse-plugin/META-INF/MANIFEST.MF
index 5e5ba41be0..a92f375886 100644
--- a/qpid/java/management/eclipse-plugin/META-INF/MANIFEST.MF
+++ b/qpid/java/management/eclipse-plugin/META-INF/MANIFEST.MF
@@ -7,6 +7,7 @@ Bundle-Activator: org.apache.qpid.management.ui.Activator
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
- org.eclipse.ui.forms
+ org.eclipse.ui.forms,
+ jmxremote.optional
Eclipse-LazyStart: true
Bundle-Vendor: Apache Software Foundation
diff --git a/qpid/java/management/eclipse-plugin/bin/qpidmc.bat b/qpid/java/management/eclipse-plugin/bin/qpidmc.bat
index 6250b53e68..e444bc5811 100644
--- a/qpid/java/management/eclipse-plugin/bin/qpidmc.bat
+++ b/qpid/java/management/eclipse-plugin/bin/qpidmc.bat
@@ -52,4 +52,4 @@ goto exit
rem Slurp the command line arguments. This loop allows for an unlimited number
rem of agruments (up to the command line limit, anyway).
-"%JAVA_HOME%\bin\java" -Xms40m -Xmx256m -Declipse.consoleLog=true -jar %QPIDMC_HOME%\eclipse\startup.jar org.eclipse.core.launcher.Main -launcher %QPIDMC_HOME%\eclipse\eclipse -name "Qpid Management Console" -showsplash 600 -configuration "file:%QPIDMC_HOME%\configuration" -os win32 -ws win32 -arch x86
+"%JAVA_HOME%\bin\java" -Xms40m -Xmx256m -Declipse.consoleLog=false -Dsecurity=PLAIN -jar %QPIDMC_HOME%\eclipse\startup.jar org.eclipse.core.launcher.Main -launcher %QPIDMC_HOME%\eclipse\eclipse -name "Qpid Management Console" -showsplash 600 -configuration "file:%QPIDMC_HOME%\configuration" -os win32 -ws win32 -arch x86
diff --git a/qpid/java/management/eclipse-plugin/bin/qpidmc.sh b/qpid/java/management/eclipse-plugin/bin/qpidmc.sh
index 2472545a14..aae61b14c7 100755
--- a/qpid/java/management/eclipse-plugin/bin/qpidmc.sh
+++ b/qpid/java/management/eclipse-plugin/bin/qpidmc.sh
@@ -61,4 +61,4 @@ elif [ $os = "Linux" ]; then
os="linux"
fi
-"$JAVA_HOME/bin/java" -Xms40m -Xmx256m -Declipse.consoleLog=false -jar $QPIDMC_HOME/eclipse/startup.jar org.eclipse.core.launcher.Main -launcher $QPIDMC_HOME/eclipse/eclipse -name "Qpid Management Console" -showsplash 600 -configuration "file:$QPIDMC_HOME/configuration" -os $os -ws $ws -arch $arch
+"$JAVA_HOME/bin/java" -Xms40m -Xmx256m -Declipse.consoleLog=false -Dsecurity=PLAIN -jar $QPIDMC_HOME/eclipse/startup.jar org.eclipse.core.launcher.Main -launcher $QPIDMC_HOME/eclipse/eclipse -name "Qpid Management Console" -showsplash 600 -configuration "file:$QPIDMC_HOME/configuration" -os $os -ws $ws -arch $arch
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
index 38a4d4561f..714f84ea49 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -41,7 +41,9 @@ public abstract class ApplicationRegistry
{
private static ImageRegistry imageRegistry = new ImageRegistry();
private static FontRegistry fontRegistry = new FontRegistry();
-
+ public static final boolean debug = Boolean.getBoolean("debug");
+ public static final String securityMechanism = System.getProperty("security", null);
+
static
{
imageRegistry.put(Constants.CONSOLE_IMAGE,
@@ -130,4 +132,9 @@ public abstract class ApplicationRegistry
_closedServerList.clear();
return list;
}
+
+ public static String getSecurityMechanism()
+ {
+ return securityMechanism;
+ }
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
index 3d163fb111..e3aedef28e 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
@@ -49,7 +49,7 @@ public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
int x = Display.getDefault().getBounds().width;
int y = Display.getDefault().getBounds().height;
- configurer.setInitialSize(new Point(4*x/5, 3*y/4));
+ configurer.setInitialSize(new Point(9*x/10, 8*y/10));
configurer.setShowCoolBar(true);
configurer.setShowStatusLine(false);
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
index 91dec841cf..da70dc736c 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
@@ -1,3 +1,4 @@
+/* Copyright Rupert Smith, 2005 to 2006, all rights reserved. */
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -7,9 +8,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -29,98 +30,110 @@ import static org.apache.qpid.management.ui.Constants.CONNECTION_PROTOCOLS;
*/
public class Constants
{
- public final static String APPLICATION_NAME = "Qpid Management Console";
-
- public final static String ACTION_REMOVE_MBEANNODE = "Remove from list";
- public final static String VALUE = "value";
- public final static String TYPE = "type";
- public final static String NODE_TYPE_SERVER = "server";
- public final static String NODE_TYPE_DOMAIN = "domain";
- public final static String NODE_TYPE_MBEANTYPE = "mbeantype";
+ public static final String APPLICATION_NAME = "Qpid Management Console";
+
+ public static final String ACTION_REMOVE_MBEANNODE = "Remove from list";
+ public static final String VALUE = "value";
+ public static final String TYPE = "type";
+ public static final String NODE_TYPE_SERVER = "server";
+ public static final String NODE_TYPE_DOMAIN = "domain";
+ public static final String NODE_TYPE_MBEANTYPE = "mbeantype";
// currently used only for virtual host instances, but will work as general also
- public final static String NODE_TYPE_TYPEINSTANCE = "mbeantype_instance";
- public final static String MBEAN = "mbean";
- public final static String ATTRIBUTE = "Attribute";
- public final static String ATTRIBUTES = "Attributes";
- public final static String NOTIFICATION = "Notifications";
- public final static String RESULT = "Result";
- public final static String VIRTUAL_HOST = "VirtualHost";
- public final static String DEFAULT_VH = "Default";
- public final static String DEFAULT_USERNAME = "guest";
- public final static String DEFAULT_PASSWORD = "guest";
-
- public final static String USERNAME = "Username";
- public final static String PASSWORD = "Password";
-
+ public static final String NODE_TYPE_TYPEINSTANCE = "mbeantype_instance";
+ public static final String MBEAN = "mbean";
+ public static final String ATTRIBUTE = "Attribute";
+ public static final String ATTRIBUTES = "Attributes";
+ public static final String NOTIFICATIONS = "Notifications";
+ public static final String RESULT = "Result";
+ public static final String VIRTUAL_HOST = "VirtualHost";
+ public static final String DEFAULT_VH = "Default";
+ public static final String DEFAULT_USERNAME = "guest";
+ public static final String DEFAULT_PASSWORD = "guest";
+
+ public static final String USERNAME = "Username";
+ public static final String PASSWORD = "Password";
+
// Attributes and operations are used to customize the GUI for Qpid. If these are changes in the
// Qpid server, then these should be updated accordingly
- public final static String ATTRIBUTE_QUEUE_OWNER = "owner";
- public final static String ATTRIBUTE_QUEUE_DEPTH = "QueueDepth";
- public final static String ATTRIBUTE_QUEUE_CONSUMERCOUNT = "ActiveConsumerCount";
- public final static String OPERATION_CREATE_QUEUE = "createNewQueue";
- public final static String OPERATION_CREATE_BINDING = "createNewBinding";
- public final static String OPERATION_MOVE_MESSAGES = "moveMessages";
-
- public final static String ALL = "All";
-
- public final static String NAVIGATION_ROOT = "Qpid Connections";
- public final static String DESCRIPTION = " Description";
-
- public final static String QUEUE = "Queue";
- public final static String CONNECTION ="Connection";
- public final static String EXCHANGE = "Exchange";
- public final static String EXCHANGE_TYPE = "ExchangeType";
- public final static String[] EXCHANGE_TYPE_VALUES = {"direct", "topic", "headers"};
- public final static String[] BOOLEAN_TYPE_VALUES = {"false", "true"};
- public final static String[] ATTRIBUTE_TABLE_TITLES = {"Attribute Name", "Value"};
- public static final String[] CONNECTION_PROTOCOLS ={"RMI"};
+ public static final String ATTRIBUTE_QUEUE_OWNER = "owner";
+ public static final String ATTRIBUTE_QUEUE_DEPTH = "QueueDepth";
+ public static final String ATTRIBUTE_QUEUE_CONSUMERCOUNT = "ActiveConsumerCount";
+ public static final String OPERATION_CREATE_QUEUE = "createNewQueue";
+ public static final String OPERATION_CREATE_BINDING = "createNewBinding";
+ public static final String OPERATION_MOVE_MESSAGES = "moveMessages";
+
+ public static final String OPERATION_CREATEUSER = "createUser";
+ public static final String OPERATION_VIEWUSERS = "viewUsers";
+ public static final String OPERATION_PARAM_USERNAME = "username";
+
+ public static final String OPERATION_SUCCESSFUL = "Operation successful";
+ public static final String OPERATION_UNSUCCESSFUL = "Operation unsuccessful";
+
+ public static final String ALL = "All";
+
+ public static final String NAVIGATION_ROOT = "Qpid Connections";
+ public static final String DESCRIPTION = " Description";
+
+ public static final String ADMIN_MBEAN_TYPE = "UserManagement";
+ public static final String QUEUE = "Queue";
+ public static final String CONNECTION = "Connection";
+ public static final String EXCHANGE = "Exchange";
+ public static final String EXCHANGE_TYPE = "ExchangeType";
+ public static final String[] EXCHANGE_TYPE_VALUES = { "direct", "fanout", "headers", "topic" };
+ public static final String[] BOOLEAN_TYPE_VALUES = { "false", "true" };
+ public static final String[] ATTRIBUTE_TABLE_TITLES = { "Attribute Name", "Value" };
+ public static final String[] CONNECTION_PROTOCOLS = { "RMI" };
public static final String DEFAULT_PROTOCOL = CONNECTION_PROTOCOLS[0];
-
- public final static String ACTION_ADDSERVER = "New Connection";
- public final static String ACTION_RECONNECT = "Reconnect";
- public final static String ACTION_LOGIN = "Login";
-
- public final static String QUEUE_SORT_BY_NAME = "Queue Name";
- public final static String QUEUE_SORT_BY_DEPTH = "Queue Depth";
- public final static String QUEUE_SORT_BY_CONSUMERCOUNT = "Consumer Count";
- public final static String QUEUE_SHOW_TEMP_QUEUES= "show temporary queues";
-
- public final static String SUBSCRIBE_BUTTON = "Subscribe";
- public final static String UNSUBSCRIBE_BUTTON = "Unsubscribe";
-
- public final static String CONSOLE_IMAGE = "ConsoelImage";
- public final static String CLOSED_FOLDER_IMAGE = "ClosedFolderImage";
- public final static String OPEN_FOLDER_IMAGE = "OpenFolderImage";
- public final static String MBEAN_IMAGE = "MBeanImage";
- public final static String NOTIFICATION_IMAGE = "NotificationImage";
-
- public final static String FONT_BUTTON = "ButtonFont";
- public final static String FONT_BOLD = "BoldFont";
- public final static String FONT_ITALIC = "ItalicFont";
- public final static String FONT_TABLE_CELL = "TableCellFont";
- public final static String FONT_NORMAL = "Normal";
-
- public final static String BUTTON_DETAILS = "Details";
- public final static String BUTTON_EDIT_ATTRIBUTE = "Edit Attribute";
- public final static String BUTTON_REFRESH = "Refresh";
- public final static String BUTTON_GRAPH = "Graph";
- public final static int TIMER_INTERVAL = 5000;
- public final static String BUTTON_EXECUTE = "Execute";
- public final static String BUTTON_CLEAR = "Clear";
- public final static String BUTTON_CONNECT = "Connect";
- public final static String BUTTON_CANCEL = "Cancel";
- public final static String BUTTON_UPDATE = "Update";
-
-
- public final static int OPERATION_IMPACT_INFO = 0;
- public final static int OPERATION_IMPACT_ACTION = 1;
- public final static int OPERATION_IMPACT_ACTIONINFO = 2;
- public final static int OPERATION_IMPACT_UNKNOWN = 3;
-
- public final static String ERROR_SERVER_CONNECTION = "Server could not be connected";
- public final static String INFO_PROTOCOL = "Please select the protocol";
- public final static String INFO_HOST_ADDRESS = "Please enter the host address";
- public final static String INFO_HOST_PORT = "Please enter the port number";
- public final static String INFO_USERNAME = "Please enter the " + USERNAME;
- public final static String INFO_PASSWORD = "Please enter the " + PASSWORD;
+
+ public static final String ACTION_ADDSERVER = "New Connection";
+ public static final String ACTION_RECONNECT = "Reconnect";
+ public static final String ACTION_LOGIN = "Login";
+
+ public static final String QUEUE_SORT_BY_NAME = "Queue Name";
+ public static final String QUEUE_SORT_BY_DEPTH = "Queue Depth";
+ public static final String QUEUE_SORT_BY_CONSUMERCOUNT = "Consumer Count";
+ public static final String QUEUE_SHOW_TEMP_QUEUES = "show temporary queues";
+
+ public static final String SUBSCRIBE_BUTTON = "Subscribe";
+ public static final String UNSUBSCRIBE_BUTTON = "Unsubscribe";
+
+ public static final String CONSOLE_IMAGE = "ConsoelImage";
+ public static final String CLOSED_FOLDER_IMAGE = "ClosedFolderImage";
+ public static final String OPEN_FOLDER_IMAGE = "OpenFolderImage";
+ public static final String MBEAN_IMAGE = "MBeanImage";
+ public static final String NOTIFICATION_IMAGE = "NotificationImage";
+
+ public static final String FONT_BUTTON = "ButtonFont";
+ public static final String FONT_BOLD = "BoldFont";
+ public static final String FONT_ITALIC = "ItalicFont";
+ public static final String FONT_TABLE_CELL = "TableCellFont";
+ public static final String FONT_NORMAL = "Normal";
+
+ public static final String BUTTON_DETAILS = "Details";
+ public static final String BUTTON_EDIT_ATTRIBUTE = "Edit Attribute";
+ public static final String BUTTON_REFRESH = "Refresh";
+ public static final String BUTTON_GRAPH = "Graph";
+ public static final int TIMER_INTERVAL = 5000;
+ public static final String BUTTON_EXECUTE = "Execute";
+ public static final String BUTTON_CLEAR = "Clear";
+ public static final String BUTTON_CONNECT = "Connect";
+ public static final String BUTTON_CANCEL = "Cancel";
+ public static final String BUTTON_UPDATE = "Update";
+
+ public static final int OPERATION_IMPACT_INFO = 0;
+ public static final int OPERATION_IMPACT_ACTION = 1;
+ public static final int OPERATION_IMPACT_ACTIONINFO = 2;
+ public static final int OPERATION_IMPACT_UNKNOWN = 3;
+
+ public static final String ERROR_SERVER_CONNECTION = "Server could not be connected";
+ public static final String INFO_PROTOCOL = "Please select the protocol";
+ public static final String INFO_HOST_ADDRESS = "Please enter the host address";
+ public static final String INFO_HOST_PORT = "Please enter the port number";
+ public static final String INFO_USERNAME = "Please enter the " + USERNAME;
+ public static final String INFO_PASSWORD = "Please enter the " + PASSWORD;
+
+ public static final String MECH_CRAMMD5 = "CRAM-MD5";
+ public static final String MECH_PLAIN = "PLAIN";
+ public static final String SASL_CRAMMD5 = "SASL/CRAM-MD5";
+ public static final String SASL_PLAIN = "SASL/PLAIN";
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
index 38c3e8f413..31825e925d 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
@@ -20,6 +20,7 @@
*/
package org.apache.qpid.management.ui;
+import static org.apache.qpid.management.ui.Constants.*;
import java.util.HashMap;
/**
@@ -50,7 +51,7 @@ public abstract class ManagedBean extends ManagedObject
this._properties = properties;
setName(getProperty("name"));
setType(getProperty("type"));
- _virtualHostName = getProperty(Constants.VIRTUAL_HOST);
+ _virtualHostName = getProperty(VIRTUAL_HOST);
}
public String getDomain()
{
@@ -89,7 +90,7 @@ public abstract class ManagedBean extends ManagedObject
public String getVirtualHostName()
{
// To make it work with the broker with no virtual host implementation
- return _virtualHostName == null ? Constants.DEFAULT_VH : _virtualHostName;
+ return _virtualHostName == null ? DEFAULT_VH : _virtualHostName;
}
/**
@@ -106,21 +107,26 @@ public abstract class ManagedBean extends ManagedObject
public boolean isQueue()
{
- return _type.endsWith(Constants.QUEUE);
+ return _type.endsWith(QUEUE);
}
public boolean isConnection()
{
- return _type.endsWith(Constants.CONNECTION);
+ return _type.endsWith(CONNECTION);
}
public boolean isExchange()
{
- return _type.endsWith(Constants.EXCHANGE);
+ return _type.endsWith(EXCHANGE);
}
public boolean isTempQueue()
{
return (isQueue() && getName().startsWith("tmp_"));
}
+
+ public boolean isAdmin()
+ {
+ return _type.endsWith(ADMIN_MBEAN_TYPE);
+ }
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
index da49d70b88..f93200cadf 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
@@ -37,8 +37,8 @@ public class Perspective implements IPerspectiveFactory
layout.setEditorAreaVisible(false);
// standalone view meaning it can't be docked or stacked with other views, and it doesn't have a title bar.
- layout.addStandaloneView(NavigationView.ID, true, IPageLayout.LEFT, 0.25f, editorArea);
- layout.addStandaloneView(MBeanView.ID, true, IPageLayout.RIGHT, 0.75f, editorArea);
+ layout.addStandaloneView(NavigationView.ID, true, IPageLayout.LEFT, 0.30f, editorArea);
+ layout.addStandaloneView(MBeanView.ID, true, IPageLayout.RIGHT, 0.70f, editorArea);
layout.getViewLayout(NavigationView.ID).setCloseable(false);
layout.getViewLayout(MBeanView.ID).setCloseable(false);
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
index fa71ee9bc7..313e143df5 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
@@ -128,6 +128,10 @@ public abstract class ServerRegistry
return _virtualHosts;
}
+ public abstract void setUserList(List<String> list);
+
+ public abstract List<String> getUsernames();
+
public abstract void addManagedObject(ManagedBean key);
public abstract List<ManagedBean> getMBeans();
@@ -154,7 +158,7 @@ public abstract class ServerRegistry
public abstract boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type);
- public abstract void clearNotifications(ManagedBean mbean);
+ public abstract void clearNotifications(ManagedBean mbean, List<NotificationObject> list);
public ClientListener getNotificationListener()
{
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
index 5a926e6474..0e12c59de4 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
@@ -194,9 +194,6 @@ public class AddServer/* extends Action*/ implements IWorkbenchWindowActionDeleg
}
}
- //If you create it, you dispose it.
- shell.dispose();
-
// enable the main shell
_window.getShell().setEnabled(true);
_window.getShell().open();
@@ -263,7 +260,7 @@ public class AddServer/* extends Action*/ implements IWorkbenchWindowActionDeleg
user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
final Text textUser = new Text(composite, SWT.BORDER);
- textUser.setText(DEFAULT_USERNAME);
+ textUser.setText("");
textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
Label password = new Label(composite, SWT.NONE);
@@ -271,7 +268,7 @@ public class AddServer/* extends Action*/ implements IWorkbenchWindowActionDeleg
password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
- textPwd.setText(DEFAULT_PASSWORD);
+ textPwd.setText("");
//textPwd.setEchoChar('*');
textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
@@ -327,11 +324,7 @@ public class AddServer/* extends Action*/ implements IWorkbenchWindowActionDeleg
_domain = comboDomain.getText();
_addServer = true;
-
- if (!connectButton.getShell().isDisposed())
- {
- connectButton.getShell().dispose();
- }
+ shell.dispose();
}
});
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
index 8fe08462cd..9aa265ab3c 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
@@ -168,9 +168,6 @@ public class ReconnectServer implements IWorkbenchWindowActionDelegate
}
}
- //If you create it, you dispose it.
- shell.dispose();
-
// enable the main shell
_window.getShell().setEnabled(true);
_window.getShell().open();
@@ -194,7 +191,7 @@ public class ReconnectServer implements IWorkbenchWindowActionDelegate
user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
final Text textUser = new Text(composite, SWT.BORDER);
- textUser.setText(DEFAULT_USERNAME);
+ textUser.setText("");
textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
// Put cursor on this field
textUser.setFocus();
@@ -204,7 +201,7 @@ public class ReconnectServer implements IWorkbenchWindowActionDelegate
password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
- textPwd.setText(DEFAULT_PASSWORD);
+ textPwd.setText("");
textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
Composite buttonsComposite = new Composite(composite, SWT.NONE);
@@ -240,11 +237,7 @@ public class ReconnectServer implements IWorkbenchWindowActionDelegate
}
_connect = true;
-
- if (!connectButton.getShell().isDisposed())
- {
- connectButton.getShell().dispose();
- }
+ shell.dispose();
}
});
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
index 82447d645e..2be0ddbebf 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
@@ -45,10 +45,7 @@ public class ClientListener implements NotificationListener
{
ObjectName objName = null;
String type = notification.getType();
- if (MBeanUtility.isDebug())
- {
- System.out.println(type + ":" + objName);
- }
+ MBeanUtility.printOutput(type + ":" + objName);
if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type))
{
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
index b0f9928c38..816c479cf9 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
@@ -20,6 +20,10 @@
*/
package org.apache.qpid.management.ui.jmx;
+import static org.apache.qpid.management.ui.Constants.*;
+
+import java.lang.reflect.Constructor;
+import java.security.Security;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -35,8 +39,9 @@ import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
+import javax.security.sasl.SaslClientFactory;
-import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ApplicationRegistry;
import org.apache.qpid.management.ui.ManagedBean;
import org.apache.qpid.management.ui.ManagedServer;
import org.apache.qpid.management.ui.ServerRegistry;
@@ -44,6 +49,10 @@ import org.apache.qpid.management.ui.model.ManagedAttributeModel;
import org.apache.qpid.management.ui.model.NotificationInfoModel;
import org.apache.qpid.management.ui.model.NotificationObject;
import org.apache.qpid.management.ui.model.OperationDataModel;
+import org.apache.qpid.management.ui.sasl.JCAProvider;
+import org.apache.qpid.management.ui.sasl.SaslProvider;
+import org.apache.qpid.management.ui.sasl.UserPasswordCallbackHandler;
+import org.apache.qpid.management.ui.sasl.UsernameHashedPasswordCallbackHandler;
public class JMXServerRegistry extends ServerRegistry
@@ -52,11 +61,12 @@ public class JMXServerRegistry extends ServerRegistry
private JMXConnector _jmxc = null;
private MBeanServerConnection _mbsc = null;
+ private List<String> _usersList;
// When an mbean gets removed from mbean server, then the notification listener
// will add that mbean in this list.
private List<ManagedBean> _mbeansToBeRemoved = new ArrayList<ManagedBean>();
- // Map containing all managed beans and ampped with unique mbean name
+ // Map containing all managed beans and mapped with unique mbean name
private HashMap<String, ManagedBean> _mbeansMap = new HashMap<String, ManagedBean>();
// Map containing MBeanInfo for all mbeans and mapped with unique mbean name
private HashMap<String, MBeanInfo> _mbeanInfoMap = new HashMap<String, MBeanInfo>();
@@ -83,11 +93,69 @@ public class JMXServerRegistry extends ServerRegistry
{
super(server);
JMXServiceURL jmxUrl = new JMXServiceURL(server.getUrl());
- Map<String, Object> env = new HashMap<String, Object>();
- String[] creds = {server.getUser(), server.getPassword()};
- env.put(JMXConnector.CREDENTIALS, creds);
-
- _jmxc = JMXConnectorFactory.connect(jmxUrl, env);
+ Map<String, Object> env = null;
+ String securityMechanism = ApplicationRegistry.getSecurityMechanism();
+
+ if (securityMechanism != null)
+ {
+ try
+ {
+ // Check if the JMXMP connector is available
+ Class klass = Class.forName("javax.management.remote.jmxmp.JMXMPConnector");
+
+ jmxUrl = new JMXServiceURL("jmxmp", server.getHost(), server.getPort());
+ env = new HashMap<String, Object>();
+
+ if (MECH_CRAMMD5.equals(securityMechanism))
+ {
+ // For SASL/CRAM-MD5
+ Map<String, Class<? extends SaslClientFactory>> map = new HashMap<String, Class<? extends SaslClientFactory>>();
+ Class<?> clazz = Class.forName("org.apache.qpid.management.ui.sasl.CRAMMD5HashedSaslClientFactory");
+ map.put("CRAM-MD5-HASHED", (Class<? extends SaslClientFactory>) clazz);
+
+ Security.addProvider(new JCAProvider(map));
+ env.put("jmx.remote.profiles", SASL_CRAMMD5);
+ env.put("jmx.remote.sasl.callback.handler",
+ new UsernameHashedPasswordCallbackHandler(server.getUser(), server.getPassword()));
+ }
+ else if (MECH_PLAIN.equals(securityMechanism))
+ {
+ // For SASL/PLAIN
+ Security.addProvider(new SaslProvider());
+ env.put("jmx.remote.profiles", SASL_PLAIN);
+ env.put("jmx.remote.sasl.callback.handler",
+ new UserPasswordCallbackHandler(server.getUser(), server.getPassword()));
+ }
+ else
+ {
+ MBeanUtility.printOutput("Security mechanism " + securityMechanism + " is not supported.");
+ }
+
+ // Now create the instance of JMXMPConnector
+ Class[] paramTypes = {JMXServiceURL.class, Map.class};
+ Constructor cons = klass.getConstructor(paramTypes);
+
+ Object[] args = {jmxUrl, env};
+ Object theObject = cons.newInstance(args);
+
+ _jmxc = (JMXConnector)theObject;
+ _jmxc.connect();
+ MBeanUtility.printOutput("Starting JMXConnector with SASL. Server=" + server.getName());
+ }
+ catch (Exception ex)
+ {
+ // When JMXMPConnector is not available
+ MBeanUtility.printOutput("Starting JMXConnector. Server=" + server.getName());
+ jmxUrl = new JMXServiceURL(server.getUrl());
+ _jmxc = JMXConnectorFactory.connect(jmxUrl, null);
+ }
+ }
+ else
+ {
+ jmxUrl = new JMXServiceURL(server.getUrl());
+ _jmxc = JMXConnectorFactory.connect(jmxUrl, null);
+ }
+
_mbsc = _jmxc.getMBeanServerConnection();
_clientListener = new ClientListener(server);
@@ -155,10 +223,7 @@ public class JMXServerRegistry extends ServerRegistry
public void removeManagedObject(ManagedBean mbean)
{
- if (MBeanUtility.isDebug())
- {
- System.out.println("Removing MBean:" + mbean.getUniqueName());
- }
+ MBeanUtility.printOutput("Removing MBean:" + mbean.getUniqueName());
if (mbean.isQueue())
{
@@ -218,17 +283,78 @@ public class JMXServerRegistry extends ServerRegistry
list.add(obj);
}
+ /**
+ * Returns all the notification objects for a given mbean. If mbean is null, it returns
+ * notification objects for all the mbeans.
+ */
public List<NotificationObject> getNotifications(ManagedBean mbean)
{
- return _notificationsMap.get(mbean.getUniqueName());
+ if (mbean == null)
+ {
+ List<NotificationObject> totalList = new ArrayList<NotificationObject>();
+ for (List<NotificationObject> list : _notificationsMap.values())
+ {
+ totalList.addAll(list);
+ }
+ return totalList;
+ }
+ else
+ {
+ return _notificationsMap.get(mbean.getUniqueName());
+ }
}
- public void clearNotifications(ManagedBean mbean)
+ public void clearNotifications(ManagedBean mbean, List<NotificationObject> list)
{
- if (_notificationsMap.containsKey(mbean.getUniqueName()))
- _notificationsMap.get(mbean.getUniqueName()).clear();
+ if (mbean == null)
+ {
+ if (list == null || list.isEmpty())
+ {
+ // All notifications of all mbeans to be cleared
+ _notificationsMap.clear();
+ }
+ else
+ {
+ // Clear the selected notifications
+ for (NotificationObject obj : list)
+ {
+ mbean = _mbeansMap.get(obj.getSource().toString());
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.remove(obj);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (list == null || list.isEmpty())
+ {
+ // All notifications of this mbean to be cleared
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.clear();
+ }
+ }
+ else
+ {
+ // Clear the selected notifications
+ for (NotificationObject obj : list)
+ {
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.remove(obj);
+ }
+ }
+ }
+ }
}
+
+
/**
* Adds notification name and type to the map. The map contains all the notification names,
* subscribed for an mbean.
@@ -254,7 +380,7 @@ public class JMXServerRegistry extends ServerRegistry
map.put(name, list);
}
// Now add the notification type to the list
- if (Constants.ALL.equals(type))
+ if (ALL.equals(type))
{
List<NotificationInfoModel> infoList = _notificationInfoMap.get(mbean.getUniqueName());
for (NotificationInfoModel model : infoList)
@@ -313,7 +439,7 @@ public class JMXServerRegistry extends ServerRegistry
HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
if (map.containsKey(name))
{
- if (Constants.ALL.equals(type))
+ if (ALL.equals(type))
{
map.remove(name);
}
@@ -441,6 +567,16 @@ public class JMXServerRegistry extends ServerRegistry
}
return connections;
}
+
+ public void setUserList(List<String> list)
+ {
+ _usersList = list;
+ }
+
+ public List<String> getUsernames()
+ {
+ return _usersList;
+ }
public ClientNotificationListener getNotificationListener()
{
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
index 5ceeb879b4..41db11c10e 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
@@ -60,13 +60,6 @@ import org.apache.qpid.management.ui.views.ViewUtility;
*/
public class MBeanUtility
{
- private static boolean _debug;
- static
- {
- String debug = System.getProperty("debug");
- _debug = "true".equalsIgnoreCase(debug) ? true : false;
- }
-
public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
/**
@@ -149,27 +142,27 @@ public class MBeanUtility
* @param mbean managed bean
* @param ex Exception
*/
- public static void handleException(ManagedBean mbean, Exception ex)
+ public static void handleException(ManagedBean mbean, Throwable ex)
{
if (mbean == null)
{
ViewUtility.popupErrorMessage("Error", "Managed Object is null \n" + ex.toString());
- ex.printStackTrace();
+ printStackTrace(ex);
}
else if (ex instanceof IOException)
{
ViewUtility.popupErrorMessage(mbean.getInstanceName(), "IO Error occured \n" + ex.toString());
- ex.printStackTrace();
+ printStackTrace(ex);
}
else if (ex instanceof ReflectionException)
{
ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Server has thrown error \n" + ex.toString());
- ex.printStackTrace();
+ printStackTrace(ex);
}
else if (ex instanceof InstanceNotFoundException)
{
ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Managed Object Not Found \n" + ex.toString());
- ex.printStackTrace();
+ printStackTrace(ex);
}
else if (ex instanceof MBeanException)
{
@@ -188,8 +181,20 @@ public class MBeanUtility
}
else
{
- ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
- ex.printStackTrace();
+ if (ex.getCause() != null)
+ {
+ handleException(mbean, ex.getCause());
+ }
+ else
+ {
+ String msg = ex.getMessage();
+ if (msg == null)
+ {
+ msg = ex.toString();
+ }
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), msg);
+ printStackTrace(ex);
+ }
}
}
@@ -449,12 +454,19 @@ public class MBeanUtility
return Arrays.asList(domains);
}
- /**
- * return true if System property is set to true -Ddebug=true
- * @return
- */
- public static boolean isDebug()
+ public static void printOutput(String statement)
{
- return _debug;
+ if (ApplicationRegistry.debug)
+ {
+ System.out.println(statement);
+ }
+ }
+
+ private static void printStackTrace(Throwable ex)
+ {
+ if (ApplicationRegistry.debug)
+ {
+ ex.printStackTrace();
+ }
}
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
index 8ba74b3ce8..926e5f0a24 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
@@ -24,10 +24,12 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
+import javax.management.ObjectName;
+
public class NotificationObject
{
- private long _sequenceNo;
+ private long _sequenceNo;
private Date _timeStamp;
private String _message;
private Object _source;
@@ -52,6 +54,17 @@ public class NotificationObject
{
this._source = _source;
}
+
+ public String getSourceName()
+ {
+ if (_source instanceof ObjectName)
+ {
+ return ((ObjectName)_source).getKeyProperty("name");
+ }
+
+ return null;
+ }
+
public String getMessage()
{
return _message;
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
index 9b6750c21a..2b83645942 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
@@ -80,5 +80,13 @@ public class OperationData
this._returnType = returnType;
}
+ public boolean isReturnTypeBoolean()
+ {
+ return (_returnType.equals("boolean") || _returnType.equals("java.lang.Boolean"));
+ }
+ public boolean isReturnTypeVoid()
+ {
+ return (_returnType.equals("void") || _returnType.equals("java.lang.Void"));
+ }
} \ No newline at end of file
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java
new file mode 100644
index 0000000000..32a0c12344
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/CRAMMD5HashedSaslClientFactory.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslException;
+
+public class CRAMMD5HashedSaslClientFactory implements SaslClientFactory
+{
+ /** The name of this mechanism */
+ public static final String MECHANISM = "CRAM-MD5-HASHED";
+
+ public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol,
+ String serverName, Map<String, ?> props, CallbackHandler cbh)
+ throws SaslException
+ {
+ for (int i = 0; i < mechanisms.length; i++)
+ {
+ if (mechanisms[i].equals(MECHANISM))
+ {
+ if (cbh == null)
+ {
+ throw new SaslException("CallbackHandler must not be null");
+ }
+
+ String[] mechs = {"CRAM-MD5"};
+ return Sasl.createSaslClient(mechs, authorizationId, protocol, serverName, props, cbh);
+ }
+ }
+ return null;
+ }
+
+ public String[] getMechanismNames(Map props)
+ {
+ return new String[]{MECHANISM};
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/ClientSaslFactory.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/ClientSaslFactory.java
new file mode 100644
index 0000000000..ce9a273eaa
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/ClientSaslFactory.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslClientFactory;
+import javax.security.sasl.SaslException;
+
+public class ClientSaslFactory implements SaslClientFactory
+{
+ public SaslClient createSaslClient(String[] mechs, String authorizationId, String protocol,
+ String serverName, Map props, CallbackHandler cbh)
+ throws SaslException
+ {
+ for (int i = 0; i < mechs.length; i++)
+ {
+ if (mechs[i].equals("PLAIN"))
+ {
+ return new PlainSaslClient(authorizationId, cbh);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Simple-minded implementation that ignores props
+ */
+ public String[] getMechanismNames(Map props)
+ {
+ return new String[]{"PLAIN"};
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java
new file mode 100644
index 0000000000..d8189f3ac3
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/JCAProvider.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.security.Provider;
+import java.util.Map;
+
+import javax.security.sasl.SaslClientFactory;
+
+public class JCAProvider extends Provider
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates the security provider with a map from SASL mechanisms to implementing factories.
+ *
+ * @param providerMap The map from SASL mechanims to implementing factory classes.
+ */
+ public JCAProvider(Map<String, Class<? extends SaslClientFactory>> providerMap)
+ {
+ super("AMQSASLProvider", 1.0, "A JCA provider that registers all "
+ + "AMQ SASL providers that want to be registered");
+ register(providerMap);
+ }
+
+ /**
+ * Registers client factory classes for a map of mechanism names to client factory classes.
+ *
+ * @param providerMap The map from SASL mechanims to implementing factory classes.
+ */
+ private void register(Map<String, Class<? extends SaslClientFactory>> providerMap)
+ {
+ for (Map.Entry<String, Class<? extends SaslClientFactory>> me : providerMap.entrySet())
+ {
+ put("SaslClientFactory." + me.getKey(), me.getValue().getName());
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/PlainSaslClient.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/PlainSaslClient.java
new file mode 100644
index 0000000000..22190f29eb
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/PlainSaslClient.java
@@ -0,0 +1,203 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.io.*;
+import javax.security.auth.callback.*;
+import javax.security.sasl.*;
+
+public class PlainSaslClient implements SaslClient
+{
+
+ private boolean completed;
+ private CallbackHandler cbh;
+ private String authorizationID;
+ private String authenticationID;
+ private byte password[];
+ private static byte SEPARATOR = 0;
+
+ public PlainSaslClient(String authorizationID, CallbackHandler cbh) throws SaslException
+ {
+ completed = false;
+ this.cbh = cbh;
+ Object[] userInfo = getUserInfo();
+ this.authorizationID = authorizationID;
+ this.authenticationID = (String) userInfo[0];
+ this.password = (byte[]) userInfo[1];
+ if (authenticationID == null || password == null)
+ {
+ throw new SaslException("PLAIN: authenticationID and password must be specified");
+ }
+ }
+
+ public byte[] evaluateChallenge(byte[] challenge) throws SaslException
+ {
+ if (completed)
+ {
+ throw new IllegalStateException("PLAIN: authentication already " +
+ "completed");
+ }
+ completed = true;
+ try
+ {
+ byte authzid[] =
+ authorizationID == null ? null : authorizationID.getBytes("UTF8");
+ byte authnid[] = authenticationID.getBytes("UTF8");
+ byte response[] =
+ new byte[
+ password.length +
+ authnid.length +
+ 2 + // SEPARATOR
+ (authzid != null ? authzid.length : 0)
+ ];
+ int size = 0;
+ if (authzid != null) {
+ System.arraycopy(authzid, 0, response, 0, authzid.length);
+ size = authzid.length;
+ }
+ response[size++] = SEPARATOR;
+ System.arraycopy(authnid, 0, response, size, authnid.length);
+ size += authnid.length;
+ response[size++] = SEPARATOR;
+ System.arraycopy(password, 0, response, size, password.length);
+ clearPassword();
+ return response;
+ } catch (UnsupportedEncodingException e) {
+ throw new SaslException("PLAIN: Cannot get UTF-8 encoding of ids",
+ e);
+ }
+ }
+
+ public String getMechanismName()
+ {
+ return "PLAIN";
+ }
+
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ public boolean isComplete()
+ {
+ return completed;
+ }
+
+ public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException
+ {
+ if (completed) {
+ throw new IllegalStateException("PLAIN: this mechanism supports " +
+ "neither integrity nor privacy");
+ } else {
+ throw new IllegalStateException("PLAIN: authentication not " +
+ "completed");
+ }
+ }
+
+ public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
+ {
+ if (completed)
+ {
+ throw new IllegalStateException("PLAIN: this mechanism supports " +
+ "neither integrity nor privacy");
+ }
+ else
+ {
+ throw new IllegalStateException("PLAIN: authentication 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");
+ }
+ }
+
+ private void clearPassword()
+ {
+ if (password != null)
+ {
+ for (int i = 0 ; i < password.length ; i++)
+ {
+ password[i] = 0;
+ }
+ password = null;
+ }
+ }
+
+ public void dispose() throws SaslException
+ {
+ clearPassword();
+ }
+
+ protected void finalize()
+ {
+ clearPassword();
+ }
+
+ private Object[] getUserInfo() throws SaslException
+ {
+ try
+ {
+ final String userPrompt = "PLAIN authentication id: ";
+ final String pwPrompt = "PLAIN password: ";
+ NameCallback nameCb = new NameCallback(userPrompt);
+ PasswordCallback passwordCb = new PasswordCallback(pwPrompt, false);
+ cbh.handle(new Callback[] { nameCb, passwordCb });
+ String userid = nameCb.getName();
+ char pwchars[] = passwordCb.getPassword();
+ byte pwbytes[];
+ if (pwchars != null)
+ {
+ pwbytes = (new String(pwchars)).getBytes("UTF8");
+ passwordCb.clearPassword();
+ }
+ else
+ {
+ pwbytes = null;
+ }
+ return (new Object[] { userid, pwbytes });
+ }
+ 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/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/SaslProvider.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/SaslProvider.java
new file mode 100644
index 0000000000..2917de8740
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/SaslProvider.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.security.Provider;
+
+public class SaslProvider extends Provider
+{
+ private static final long serialVersionUID = -6978096016899676466L;
+
+ public SaslProvider()
+ {
+ super("SaslClientFactory", 1.0, "SASL PLAIN CLIENT MECHANISM");
+ put("SaslClientFactory.PLAIN", "ClientSaslFactory");
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UserPasswordCallbackHandler.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UserPasswordCallbackHandler.java
new file mode 100644
index 0000000000..1602229c85
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UserPasswordCallbackHandler.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.io.*;
+import javax.security.auth.callback.*;
+
+public class UserPasswordCallbackHandler implements CallbackHandler
+{
+ private String user;
+ private char[] pwchars;
+
+ public UserPasswordCallbackHandler(String user, String password)
+ {
+ this.user = user;
+ this.pwchars = password.toCharArray();
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ NameCallback ncb = (NameCallback) callbacks[i];
+ ncb.setName(user);
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ PasswordCallback pcb = (PasswordCallback) callbacks[i];
+ pcb.setPassword(pwchars);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+ }
+
+ private void clearPassword()
+ {
+ if (pwchars != null)
+ {
+ for (int i = 0 ; i < pwchars.length ; i++)
+ {
+ pwchars[i] = 0;
+ }
+ pwchars = null;
+ }
+ }
+
+ protected void finalize()
+ {
+ clearPassword();
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java
new file mode 100644
index 0000000000..f4e3d2661e
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/sasl/UsernameHashedPasswordCallbackHandler.java
@@ -0,0 +1,82 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.ui.sasl;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.qpid.management.ui.views.ViewUtility;
+
+public class UsernameHashedPasswordCallbackHandler implements CallbackHandler
+{
+ private String user;
+ private char[] pwchars;
+
+ public UsernameHashedPasswordCallbackHandler(String user, String password) throws Exception
+ {
+ this.user = user;
+ this.pwchars = ViewUtility.getHash(password);
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ NameCallback ncb = (NameCallback) callbacks[i];
+ ncb.setName(user);
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ PasswordCallback pcb = (PasswordCallback) callbacks[i];
+ pcb.setPassword(pwchars);
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+ }
+
+
+ private void clearPassword()
+ {
+ if (pwchars != null)
+ {
+ for (int i = 0 ; i < pwchars.length ; i++)
+ {
+ pwchars[i] = 0;
+ }
+ pwchars = null;
+ }
+ }
+
+ protected void finalize()
+ {
+ clearPassword();
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
index 437afeeda1..a7e8bbfc4c 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
@@ -596,7 +596,7 @@ public class AttributesTabControl extends TabControl
}
// Refresh from the server registry
- private void refresh()
+ public void refresh()
{
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
ManagedAttributeModel attributesList = serverRegistry.getAttributeModel(_mbean);
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
index 59b9fe3aaa..344c3c4e7f 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
@@ -62,6 +62,7 @@ public class MBeanView extends ViewPart
private FormToolkit _toolkit = null;
private Form _form = null;
+ private String _formText = APPLICATION_NAME;
private static ManagedServer _server = null;
private TreeObject _selectedNode = null;
private ManagedBean _mbean = null;
@@ -73,6 +74,8 @@ public class MBeanView extends ViewPart
// TabFolder to list all the mbeans for a given mbeantype(eg Connection, Queue, Exchange)
private TabFolder typeTabFolder = null;
+
+ private TabFolder notificationTabFolder = null;
/*
* Listener for the selection events in the navigation view
*/
@@ -91,16 +94,41 @@ public class MBeanView extends ViewPart
// an mbeantype. For mbeantype selection(eg Connection, Queue, Exchange) _mbean will remain null.
_mbean = null;
setInvisible();
- _form.setText(APPLICATION_NAME);
- // If a selected node(mbean) gets unregistered from mbena server, mbenaview should should
+ // If a selected node(mbean) gets unregistered from mbean server, mbeanview should
// make the tabfolber for that mbean invisible
if (_selectedNode == null)
return;
setServer();
refreshMBeanView();
+ setFormTitle();
+ }
+ }
+
+ private void setFormTitle()
+ {
+ if (_mbean != null)
+ {
+ _formText = _mbean.getType();
+ if ((_mbean.getVirtualHostName() != null) && (!DEFAULT_VH.equals(_mbean.getVirtualHostName())) )
+ {
+ _formText = _formText.replaceFirst(VIRTUAL_HOST, _mbean.getVirtualHostName());
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ _formText = _formText + ": " + _mbean.getName();
+ }
+ }
+ }
+ else if ((_selectedNode.getVirtualHost() != null) && (!DEFAULT_VH.equals(_selectedNode.getVirtualHost())))
+ {
+ _formText = _selectedNode.getVirtualHost();
}
+ else
+ {
+ _formText = APPLICATION_NAME;
+ }
+ _form.setText(_formText);
}
public void refreshMBeanView()
@@ -121,10 +149,16 @@ public class MBeanView extends ViewPart
{
refreshTypeTabFolder(_selectedNode.getName());
}
- else
+ else if (NOTIFICATIONS.equals(_selectedNode.getType()))
+ {
+ refreshNotificationPage();
+ }
+ else if (MBEAN.equals(_selectedNode.getType()))
{
+ _mbean = (ManagedBean)_selectedNode.getManagedObject();
showSelectedMBean();
}
+
_form.layout(true);
_form.getBody().layout(true, true);
}
@@ -174,20 +208,7 @@ public class MBeanView extends ViewPart
}
private void showSelectedMBean() throws Exception
- {
- if (NOTIFICATION.equals(_selectedNode.getType()))
- {
- _mbean = (ManagedBean)_selectedNode.getParent().getManagedObject();
- }
- else if (MBEAN.equals(_selectedNode.getType()))
- {
- _mbean = (ManagedBean)_selectedNode.getManagedObject();
- }
- else
- {
- return;
- }
-
+ {
try
{
MBeanUtility.getMBeanInfo(_mbean);
@@ -213,14 +234,8 @@ public class MBeanView extends ViewPart
tabFolder = createMBeanTabFolder();
}
- String text = _mbean.getType();
- if (_mbean.getName() != null && _mbean.getName().length() != 0)
- {
- text = text + ": " + _mbean.getName();
- }
- _form.setText(text);
int tabIndex = 0;
- if (NOTIFICATION.equals(_selectedNode.getType()))
+ if (NOTIFICATIONS.equals(_selectedNode.getType()))
{
tabIndex = tabFolder.getItemCount() -1;
}
@@ -247,6 +262,8 @@ public class MBeanView extends ViewPart
// Add mbeantype TabFolder. This will list all the mbeans under a mbeantype (eg Queue, Exchange).
// Using this list mbeans will be added in the navigation view
createMBeanTypeTabFolder();
+
+ createNotificationsTabFolder();
}
private TabFolder createMBeanTabFolder()
@@ -345,7 +362,7 @@ public class MBeanView extends ViewPart
NotificationsTabControl controller = new NotificationsTabControl(tabFolder);
TabItem tab = new TabItem(tabFolder, SWT.NONE);
- tab.setText(NOTIFICATION);
+ tab.setText(NOTIFICATIONS);
tab.setData(CONTROLLER, controller);
tab.setControl(controller.getControl());
}
@@ -432,6 +449,32 @@ public class MBeanView extends ViewPart
});
}
+ private void createNotificationsTabFolder()
+ {
+ notificationTabFolder = new TabFolder(_form.getBody(), SWT.NONE);
+ FormData layoutData = new FormData();
+ layoutData.left = new FormAttachment(0);
+ layoutData.top = new FormAttachment(0);
+ layoutData.right = new FormAttachment(100);
+ layoutData.bottom = new FormAttachment(100);
+ notificationTabFolder.setLayoutData(layoutData);
+ notificationTabFolder.setVisible(false);
+
+ VHNotificationsTabControl controller = new VHNotificationsTabControl(notificationTabFolder);
+ TabItem tab = new TabItem(notificationTabFolder, SWT.NONE);
+ tab.setText(NOTIFICATIONS);
+ tab.setData(CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+ }
+
+ private void refreshNotificationPage()
+ {
+ TabItem tab = notificationTabFolder.getItem(0);
+ VHNotificationsTabControl controller = (VHNotificationsTabControl)tab.getData(CONTROLLER);
+ controller.refresh();
+ notificationTabFolder.setVisible(true);
+ }
+
/**
* Refreshes the Selected mbeantype tab. The control lists all the available mbeans
* for an mbeantype(eg Queue, Exchange etc)
@@ -492,6 +535,11 @@ public class MBeanView extends ViewPart
{
typeTabFolder.setVisible(false);
}
+
+ if (notificationTabFolder != null)
+ {
+ notificationTabFolder.setVisible(false);
+ }
}
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
index a861405d30..68f95e01f0 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
@@ -244,7 +244,8 @@ public class NavigationView extends ViewPart
List<TreeObject> list = _serversRootNode.getChildren();
for (TreeObject node : list)
{
- if (url.equals(node.getUrl()))
+ ManagedServer nodeServer = (ManagedServer)node.getManagedObject();
+ if (url.equals(nodeServer.getUrl()))
{
// Server is already in the list of added servers, so now connect it.
// Set the server node as selected and then connect it.
@@ -266,7 +267,6 @@ public class NavigationView extends ViewPart
// Server connection is successful. Now add the server in the tree
TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
- serverNode.setUrl(url);
serverNode.setManagedObject(managedServer);
_serversRootNode.addChild(serverNode);
@@ -504,6 +504,11 @@ public class NavigationView extends ViewPart
typeChild = new TreeObject(QUEUE, NODE_TYPE_MBEANTYPE);
typeChild.setParent(parent);
typeChild.setVirtualHost(parent.getVirtualHost());
+
+ // Add common notification node for virtual host
+ TreeObject notificationNode = new TreeObject(NOTIFICATIONS, NOTIFICATIONS);
+ notificationNode.setParent(parent);
+ notificationNode.setVirtualHost(parent.getVirtualHost());
}
/**
@@ -585,7 +590,10 @@ public class NavigationView extends ViewPart
// create a node for "type"
typeNode = createTypeNode(parentNode, type);
- typeNode.setVirtualHost(mbean.getVirtualHostName());
+ if (!type.equals(VIRTUAL_HOST))
+ {
+ typeNode.setVirtualHost(mbean.getVirtualHostName());
+ }
}
// now type node create becomes the parent node for next node in hierarchy
@@ -641,8 +649,8 @@ public class NavigationView extends ViewPart
// Add notification node
// TODO: show this only if the mbean sends any notification
- TreeObject notificationNode = new TreeObject(NOTIFICATION, NOTIFICATION);
- notificationNode.setParent(mbeanNode);
+ //TreeObject notificationNode = new TreeObject(NOTIFICATION, NOTIFICATION);
+ //notificationNode.setParent(mbeanNode);
}
private TreeObject createTypeNode(TreeObject parent, String name)
@@ -1044,7 +1052,7 @@ public class NavigationView extends ViewPart
public Image getImage(Object element)
{
TreeObject node = (TreeObject) element;
- if (node.getType().equals(NOTIFICATION))
+ if (node.getType().equals(NOTIFICATIONS))
{
return ApplicationRegistry.getImage(NOTIFICATION_IMAGE);
}
@@ -1107,8 +1115,11 @@ public class NavigationView extends ViewPart
{
return 1;
}
-
- return 2;
+ if (node.getType().equals(NOTIFICATIONS))
+ {
+ return 2;
+ }
+ return 3;
}
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
index 4f0acde1b4..6894080859 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
@@ -20,29 +20,28 @@
*/
package org.apache.qpid.management.ui.views;
-import java.util.ArrayList;
+import static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
+import static org.apache.qpid.management.ui.Constants.BUTTON_REFRESH;
+import static org.apache.qpid.management.ui.Constants.DESCRIPTION;
+import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
+import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
+import static org.apache.qpid.management.ui.Constants.FONT_ITALIC;
+import static org.apache.qpid.management.ui.Constants.SUBSCRIBE_BUTTON;
+import static org.apache.qpid.management.ui.Constants.UNSUBSCRIBE_BUTTON;
+
import java.util.List;
-import static org.apache.qpid.management.ui.Constants.*;
import org.apache.qpid.management.ui.ApplicationRegistry;
import org.apache.qpid.management.ui.ManagedBean;
import org.apache.qpid.management.ui.ServerRegistry;
import org.apache.qpid.management.ui.jmx.MBeanUtility;
import org.apache.qpid.management.ui.model.NotificationInfoModel;
import org.apache.qpid.management.ui.model.NotificationObject;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
@@ -52,71 +51,35 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.widgets.Form;
-import org.eclipse.ui.forms.widgets.FormToolkit;
/**
* Creates control composite for Notifications tab
* @author Bhupendra Bhardwaj
*/
-public class NotificationsTabControl extends TabControl
-{
- private FormToolkit _toolkit;
- private Form _form;
- private Table table = null;
- private TableViewer _tableViewer = null;
-
- private IStructuredContentProvider contentProvider = new ContentProviderImpl();
- private SelectionListener selectionListener = new SelectionListenerImpl();
- private SelectionListener comboListener = new ComboSelectionListener();
-
- private Thread worker = null;
-
- private List<NotificationObject> _notifications = null;
- private static final String COLUMN_SEQ = "Sequence No";
- private static final String COLUMN_TIME = "TimeStamp";
- private static final String COLUMN_TYPE = "Type";
- private static final String COLUMN_MSG = "Notification Message";
- private static final String[] _tableTitles = new String [] {
- COLUMN_SEQ,
- COLUMN_TIME,
- COLUMN_TYPE,
- COLUMN_MSG
- };
+public class NotificationsTabControl extends VHNotificationsTabControl
+{
+ private static final String SELECT_NOTIFICATIONNAME = "Select Notification";
+ private static final String SELECT_NOTIFICATIONTYPE = "Select Type";
+ private SelectionListener selectionListener;
+ private SelectionListener comboListener;
private Combo notificationNameCombo = null;
private Combo typesCombo = null;
private Label descriptionLabel = null;
private Button _subscribeButton = null;
private Button _unsubscribeButton = null;
- private Button _clearButton = null;
- private Button _refreshButton = null;
-
public NotificationsTabControl(TabFolder tabFolder)
{
super(tabFolder);
- _toolkit = new FormToolkit(_tabFolder.getDisplay());
- _form = _toolkit.createForm(_tabFolder);
- GridLayout gridLayout = new GridLayout();
- gridLayout.marginWidth = 0;
- gridLayout.marginHeight = 0;
- _form.getBody().setLayout(gridLayout);
-
- createWidgets();
- worker = new Thread(new Worker());
- worker.start();
}
- private void createWidgets()
+ protected void createWidgets()
{
+ selectionListener = new SelectionListenerImpl();
+ comboListener = new ComboSelectionListener();
createNotificationInfoComposite();
//addFilterComposite();
addButtons();
@@ -124,14 +87,6 @@ public class NotificationsTabControl extends TabControl
}
/**
- * @see TabControl#getControl()
- */
- public Control getControl()
- {
- return _form;
- }
-
- /**
* Creates composite and populates for displaying Notification Information (name, type, description)
* and creates buttons for subscribing or unsubscribing for notifications
*/
@@ -205,7 +160,7 @@ public class NotificationsTabControl extends TabControl
/**
* Creates clear buttin and refresh button
*/
- private void addButtons()
+ protected void addButtons()
{
Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
@@ -224,8 +179,9 @@ public class NotificationsTabControl extends TabControl
if (_mbean == null)
return;
+ IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
- serverRegistry.clearNotifications(_mbean);
+ serverRegistry.clearNotifications(_mbean, ss.toList());
refresh();
}
});
@@ -247,155 +203,13 @@ public class NotificationsTabControl extends TabControl
}
});
}
-
- /**
- * Creates table to display notifications
- */
- private void createTable()
- {
- table = _toolkit.createTable(_form.getBody(), SWT.FULL_SELECTION);
- table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- TableColumn column = new TableColumn(table, SWT.NONE);
- column.setText(_tableTitles[0]);
- column.pack(); //column.setWidth(200);
-
- column = new TableColumn(table, SWT.NONE);
- column.setText(_tableTitles[1]);
- column.setWidth(150);
-
- column = new TableColumn(table, SWT.NONE);
- column.setText(_tableTitles[2]);
- column.setWidth(100);
-
- column = new TableColumn(table, SWT.NONE);
- column.setText(_tableTitles[3]);
- column.setWidth(500);
-
- table.setHeaderVisible(true);
- table.setLinesVisible(true);
- }
-
- /**
- * Creates JFace viewer for the notifications table
- */
- protected void createTableViewer()
- {
- createTable();
- _tableViewer = new TableViewer(table);
- //_tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- _tableViewer.setUseHashlookup(true);
- _tableViewer.setContentProvider(contentProvider);
- _tableViewer.setLabelProvider(new LabelProviderImpl());
- _tableViewer.setColumnProperties(_tableTitles);
- /*
- CellEditor[] cellEditors = new CellEditor[_tableTitles.length];
- TextCellEditor textEditor = new TextCellEditor(table);
- cellEditors[0] = textEditor;
- textEditor = new TextCellEditor(table);
- cellEditors[1] = textEditor;
- textEditor = new TextCellEditor(table);
- cellEditors[2] = textEditor;
- textEditor = new TextCellEditor(table);
- cellEditors[3] = textEditor;
-
- // Assign the cell editors to the viewer
- _tableViewer.setCellEditors(cellEditors);
- _tableViewer.setCellModifier(new TableCellModifier());
- */
-
- addTableListeners();
-
- //_tableViewer.addSelectionChangedListener(new );
-
- //_notificationDetails = new Composite(_tabControl, SWT.BORDER);
- //_notificationDetails.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- //_tabControl.layout();
- //viewerComposite.layout();
- }
-
- /**
- * Adds listeners to the viewer for displaying notification details
- */
- private void addTableListeners()
- {
- _tableViewer.addDoubleClickListener(new IDoubleClickListener()
- {
- Display display = null;
- Shell shell = null;
- public void doubleClick(DoubleClickEvent event)
- {
- display = Display.getCurrent();
- shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN |
- SWT.MAX | SWT.RESIZE);
- shell.setText("Notification");
-
- int x = display.getBounds().width;
- int y = display.getBounds().height;
- shell.setBounds(x/4, y/4, x/2, y/3);
- StructuredSelection selection = (StructuredSelection)event.getSelection();
- createPopupContents((NotificationObject)selection.getFirstElement());
- shell.open();
- while (!shell.isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- }
-
- //If you create it, you dispose it.
- shell.dispose();
- }
-
- private void createPopupContents(NotificationObject obj)
- {
- shell.setLayout(new GridLayout());
-
- Composite parent = new Composite(shell, SWT.NONE);
- parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- GridLayout layout = new GridLayout(4, true);
- parent.setLayout(layout);
-
- Label key = new Label(parent, SWT.TRAIL);
- key.setText(COLUMN_SEQ);
- GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
- key.setLayoutData(layoutData);
- Text value = new Text(parent, SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
- value.setText(""+obj.getSequenceNo());
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- // Time row
- key = new Label(parent, SWT.TRAIL);
- key.setText(COLUMN_TIME);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
- value.setText(""+obj.getTimeStamp());
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- key = new Label(parent, SWT.TRAIL);
- key.setText(COLUMN_TYPE);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
- value.setText(""+obj.getType());
- value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
-
- key = new Label(parent, SWT.TRAIL);
- key.setText(COLUMN_MSG);
- key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
- value = new Text(parent, SWT.MULTI | SWT.WRAP| SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
- value.setText(""+obj.getMessage());
- GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
- gridData.heightHint = 100;
- value.setLayoutData(gridData);
- }
- });
- }
-
+
@Override
public void refresh(ManagedBean mbean)
{
_mbean = mbean;
_notifications = null;
+ _table.deselectAll();
_tableViewer.getTable().clearAll();
if (_mbean == null)
@@ -431,9 +245,10 @@ public class NotificationsTabControl extends TabControl
_form.getBody().layout(true, true);
}
- private void refresh()
+ public void refresh()
{
_notifications = null;
+ _table.deselectAll();
_tableViewer.getTable().clearAll();
}
@@ -444,7 +259,11 @@ public class NotificationsTabControl extends TabControl
{
notificationNameCombo.removeAll();
NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(_mbean);
- notificationNameCombo.add("Select Notification");
+ if (items.length > 1)
+ {
+ notificationNameCombo.add(SELECT_NOTIFICATIONNAME);
+ }
+
for (int i = 0; i < items.length; i++)
{
notificationNameCombo.add(items[i].getName());
@@ -457,6 +276,7 @@ public class NotificationsTabControl extends TabControl
typesCombo.select(0);
typesCombo.setEnabled(false);
+ populateNotificationType(notificationNameCombo.getItem(0));
checkForEnablingButtons();
}
@@ -466,7 +286,8 @@ public class NotificationsTabControl extends TabControl
private void checkForEnablingButtons()
{
int nameIndex = notificationNameCombo.getSelectionIndex();
- if (nameIndex == 0)
+ int itemCount = notificationNameCombo.getItems().length;
+ if ((itemCount > 1) && (nameIndex == 0))
{
_subscribeButton.setEnabled(false);
_unsubscribeButton.setEnabled(false);
@@ -475,7 +296,8 @@ public class NotificationsTabControl extends TabControl
}
int typeIndex = typesCombo.getSelectionIndex();
- if (typeIndex == 0)
+ itemCount = typesCombo.getItems().length;
+ if ((itemCount > 1) && (typeIndex == 0))
{
_subscribeButton.setEnabled(false);
_unsubscribeButton.setEnabled(false);
@@ -560,164 +382,38 @@ public class NotificationsTabControl extends TabControl
Combo combo = (Combo)e.getSource();
if (combo == notificationNameCombo)
{
- if (combo.getSelectionIndex() == 0)
- {
- descriptionLabel.setText("");
- typesCombo.select(0);
- typesCombo.setEnabled(false);
- return;
- }
- String index = combo.getItem(combo.getSelectionIndex());
- NotificationInfoModel data = (NotificationInfoModel)combo.getData(index);
- descriptionLabel.setText(data.getDescription());
- typesCombo.removeAll();
- typesCombo.setItems(data.getTypes());
- typesCombo.add("Select Type", 0);
- typesCombo.select(0);
- typesCombo.setEnabled(true);
+ String selectedItem = combo.getItem(combo.getSelectionIndex());
+ populateNotificationType(selectedItem);
}
checkForEnablingButtons();
}
}
- /**
- * Content provider class for the table viewer
- */
- private class ContentProviderImpl implements IStructuredContentProvider, INotificationViewer
+ private void populateNotificationType(String notificationName)
{
- public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ NotificationInfoModel data = (NotificationInfoModel)notificationNameCombo.getData(notificationName);
+ if (data == null)
{
-
- }
- public void dispose()
- {
-
- }
- public Object[] getElements(Object parent)
- {
- return _notifications.toArray(new NotificationObject[0]);
- }
- public void addNotification(NotificationObject notification)
- {
- _tableViewer.add(notification);
- }
-
- public void addNotification(List<NotificationObject> notificationList)
- {
- _tableViewer.add(notificationList.toArray(new NotificationObject[0]));
- }
- }
-
- /**
- * Label provider for the table viewer
- */
- private class LabelProviderImpl implements ITableLabelProvider
- {
- List<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
- public void addListener(ILabelProviderListener listener)
- {
- listeners.add(listener);
- }
-
- public void dispose(){
-
- }
-
- public Image getColumnImage(Object element, int columnIndex)
- {
- return null;
- }
-
- public String getColumnText(Object element, int columnIndex)
- {
- String result = null;
- NotificationObject t = (NotificationObject)element;
- switch(columnIndex)
- {
- case 0 :
- result = String.valueOf(t.getSequenceNo());
- break;
- case 1 :
- result = String.valueOf(t.getTimeStamp());
- break;
- case 2 :
- result = t.getType();
- break;
- case 3 :
- result = t.getMessage();
- break;
- default :
- result = "";
- }
-
- return result;
- }
-
- public boolean isLabelProperty(Object element, String property)
- {
- return false;
- }
-
- public void removeListener(ILabelProviderListener listener)
- {
- listeners.remove(listener);
- }
- } // end of LabelProviderImpl
-
- private boolean workerRunning = false;
- private void setWorkerRunning(boolean running)
- {
- workerRunning = running;
- }
-
- /**
- * Worker class which keeps looking if there are new notifications coming from server for the selected mbean
- */
- private class Worker implements Runnable
- {
- public void run()
- {
- Display display = _tabFolder.getDisplay();
- while(true)
- {
- if (!workerRunning || _mbean == null || display == null)
- {
- sleep();
- continue;
- }
-
- display.syncExec(new Runnable()
- {
- public void run()
- {
- setWorkerRunning(_form.isVisible());
- if (!workerRunning) return;
-
- updateTableViewer();
- }
- });
-
- sleep();
- }
+ descriptionLabel.setText("");
+ typesCombo.select(0);
+ typesCombo.setEnabled(false);
+ return;
}
-
- private void sleep()
+ descriptionLabel.setText(data.getDescription());
+ typesCombo.removeAll();
+ typesCombo.setItems(data.getTypes());
+ if (typesCombo.getItemCount() > 1)
{
- try
- {
- Thread.sleep(2000);
- }
- catch(Exception ex)
- {
-
- }
+ typesCombo.add(SELECT_NOTIFICATIONTYPE, 0);
}
+ typesCombo.select(0);
+ typesCombo.setEnabled(true);
}
/**
* Updates the table with new notifications received from mbean server for the selected mbean
*/
- private void updateTableViewer()
+ protected void updateTableViewer()
{
ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
List<NotificationObject> newList = serverRegistry.getNotifications(_mbean);
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
index 49b61c0fc6..2ac037e4f0 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
@@ -20,10 +20,16 @@
*/
package org.apache.qpid.management.ui.views;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+
import static org.apache.qpid.management.ui.Constants.*;
import org.apache.qpid.management.ui.ApplicationRegistry;
import org.apache.qpid.management.ui.ManagedBean;
@@ -76,7 +82,7 @@ public class OperationTabControl extends TabControl
private SelectionListener operationExecutionListener = new OperationExecutionListener();
private SelectionListener refreshListener = new RefreshListener();
private SelectionListener parameterSelectionListener = new ParameterSelectionListener();
- private SelectionListener bolleanSelectionListener = new BooleanSelectionListener();
+ private SelectionListener booleanSelectionListener = new BooleanSelectionListener();
private VerifyListener verifyListener = new VerifyListenerImpl();
private KeyListener keyListener = new KeyListenerImpl();
private KeyListener headerBindingListener = new HeaderBindingKeyListener();
@@ -249,6 +255,8 @@ public class OperationTabControl extends TabControl
formData.top = new FormAttachment(0, parameterPositionOffset);
formData.left = new FormAttachment(label, 5);
formData.right = new FormAttachment(valueWidth);
+ // this will contain the list of items, if the list is to be made available to choose from
+ // e.g. the list of exchanges
String[] items = null;
if (param.getName().equals(QUEUE))
{
@@ -269,6 +277,15 @@ public class OperationTabControl extends TabControl
{
items = EXCHANGE_TYPE_VALUES;
}
+ else if (_mbean.isAdmin() && param.getName().equals(OPERATION_PARAM_USERNAME)
+ && !_opData.getName().equals(OPERATION_CREATEUSER))
+ {
+ List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
+ if (list != null && !list.isEmpty())
+ {
+ items = list.toArray(new String[0]);
+ }
+ }
if (items != null)
{
@@ -295,12 +312,17 @@ public class OperationTabControl extends TabControl
Button booleanButton = _toolkit.createButton(_paramsComposite, "", SWT.CHECK);
booleanButton.setLayoutData(formData);
booleanButton.setData(param);
- booleanButton.addSelectionListener(bolleanSelectionListener);
+ booleanButton.addSelectionListener(booleanSelectionListener);
valueInCombo = true;
}
else
{
- Text text = _toolkit.createText(_paramsComposite, "", SWT.NONE);
+ int style = SWT.NONE;
+ if (PASSWORD.equalsIgnoreCase(param.getName()))
+ {
+ style = SWT.PASSWORD;
+ }
+ Text text = _toolkit.createText(_paramsComposite, "", style);
formData = new FormData();
formData.top = new FormAttachment(0, parameterPositionOffset);
formData.left = new FormAttachment(label, 5);
@@ -530,6 +552,8 @@ public class OperationTabControl extends TabControl
((org.eclipse.swt.widgets.List)controls[i]).deselectAll();
else if (controls[i] instanceof Text)
((Text)controls[i]).setText("");
+ else if (controls[i] instanceof Button)
+ ((Button)controls[i]).setSelection(false);
else if (controls[i] instanceof Composite)
clearParameterValues((Composite)controls[i]);
}
@@ -557,6 +581,21 @@ public class OperationTabControl extends TabControl
}
// End of custom code
+
+ // customized for passwords
+ if (PASSWORD.equalsIgnoreCase(param.getName()))
+ {
+ try
+ {
+ param.setValueFromString(ViewUtility.getHashedString(param.getValue()));
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ return;
+ }
+ }
+ // end of customization
ViewUtility.popupInfoMessage(_form.getText(),
"Please select the " + ViewUtility.getDisplayText(param.getName()));
@@ -609,6 +648,17 @@ public class OperationTabControl extends TabControl
return;
}
+ // Custom code for Admin mbean operation
+ /* These custome codes here are to make the GUI look more user friendly.
+ * Here we are adding the users to a list, which will be used to list username to be selected on
+ * pages like "delete user", "set password" instead of typing the username
+ */
+ if (_mbean.isAdmin() && _opData.getName().equals(OPERATION_VIEWUSERS))
+ {
+ ApplicationRegistry.getServerRegistry(_mbean).setUserList(extractUserList(result));
+ }
+ // end of custom code
+
// Some mbeans have only "type" and no "name".
String title = _mbean.getType();
if (_mbean.getName() != null && _mbean.getName().length() != 0)
@@ -616,9 +666,15 @@ public class OperationTabControl extends TabControl
title = _mbean.getName();
}
- if (_opData.getReturnType().equals("void") || _opData.getReturnType().equals("java.lang.Void"))
+ if (_opData.isReturnTypeVoid())
+ {
+ ViewUtility.popupInfoMessage(title, OPERATION_SUCCESSFUL);
+ }
+ else if (_opData.isReturnTypeBoolean())
{
- ViewUtility.popupInfoMessage(title, "Operation successful");
+ boolean success = Boolean.parseBoolean(result.toString());
+ String message = success ? OPERATION_SUCCESSFUL : OPERATION_UNSUCCESSFUL;
+ ViewUtility.popupInfoMessage(title, message);
}
else if (_opData.getParameters() != null && !_opData.getParameters().isEmpty())
{
@@ -634,6 +690,24 @@ public class OperationTabControl extends TabControl
}
+ private List<String> extractUserList(Object result)
+ {
+ if (!(result instanceof TabularDataSupport))
+ {
+ return null;
+ }
+
+ TabularDataSupport tabularData = (TabularDataSupport)result;
+ Collection<CompositeData> records = tabularData.values();
+ List<String> list = new ArrayList<String>();
+ for (CompositeData data : records)
+ {
+ list.add(data.get(USERNAME).toString());
+ }
+ Collections.sort(list);
+ return list;
+ }
+
/**
* Listener class for the operation parameters widget
*/
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
index 0793e33538..c13c92066c 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
@@ -69,7 +69,18 @@ public abstract class TabControl
return null;
}
- public abstract void refresh(ManagedBean mbean);
+ public void refresh(ManagedBean mbean)
+ {
+ if (mbean == null)
+ {
+ refresh();
+ }
+ }
+
+ public void refresh()
+ {
+
+ }
public void refresh(ManagedBean mbean, OperationData opData)
{
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
index 511c2d7150..9545ed9876 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
@@ -31,7 +31,6 @@ public class TreeObject
{
private String _name;
private String _type;
- private String _url;
private String _virtualHost;
private TreeObject _parent;
private List<TreeObject> _children = new ArrayList<TreeObject>();
@@ -88,16 +87,6 @@ public class TreeObject
{
return _type;
}
-
- public String getUrl()
- {
- return _url;
- }
-
- public void setUrl(String url)
- {
- this._url = url;
- }
public String getVirtualHost()
{
@@ -131,7 +120,6 @@ public class TreeObject
if (parent != null)
{
- this._url = parent.getUrl();
parent.addChild(this);
}
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
new file mode 100644
index 0000000000..258f5ce02a
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
@@ -0,0 +1,462 @@
+package org.apache.qpid.management.ui.views;
+
+import static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
+import static org.apache.qpid.management.ui.Constants.BUTTON_REFRESH;
+import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
+import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.model.NotificationObject;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public class VHNotificationsTabControl extends TabControl
+{
+ protected FormToolkit _toolkit;
+ protected Form _form;
+ protected Table _table = null;
+ protected TableViewer _tableViewer = null;
+
+ protected Thread worker = null;
+
+ protected List<NotificationObject> _notifications = null;
+
+ private static final String COLUMN_OBJ = "Object Name";
+ private static final String COLUMN_SEQ = "Sequence No";
+ private static final String COLUMN_TIME = "TimeStamp";
+ private static final String COLUMN_TYPE = "Type";
+ private static final String COLUMN_MSG = "Notification Message";
+ protected static final String[] _tableTitles = new String [] {
+ COLUMN_OBJ,
+ COLUMN_SEQ,
+ COLUMN_TIME,
+ COLUMN_TYPE,
+ COLUMN_MSG
+ };
+
+ protected Button _clearButton = null;
+ protected Button _refreshButton = null;
+
+ public VHNotificationsTabControl(TabFolder tabFolder)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ _form.getBody().setLayout(gridLayout);
+
+ worker = new Thread(new Worker());
+ worker.start();
+ }
+
+ protected void createWidgets()
+ {
+ addButtons();
+ createTableViewer();
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ if (_table == null)
+ {
+ createWidgets();
+ }
+ return _form;
+ }
+
+ /**
+ * Creates clear buttin and refresh button
+ */
+ protected void addButtons()
+ {
+ Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ composite.setLayout(new GridLayout(2, true));
+
+ // Add Clear Button
+ _clearButton = _toolkit.createButton(composite, BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
+ _clearButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ GridData gridData = new GridData(SWT.LEAD, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _clearButton.setLayoutData(gridData);
+ _clearButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ //TODO : Get selected rows and clear those
+ IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
+ serverRegistry.clearNotifications(null, ss.toList());
+ refresh();
+ }
+ });
+
+ // Add Refresh Button
+ _refreshButton = _toolkit.createButton(composite, BUTTON_REFRESH, SWT.PUSH | SWT.CENTER);
+ _refreshButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ gridData = new GridData(SWT.TRAIL, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _refreshButton.setLayoutData(gridData);
+ _refreshButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ refresh();
+ }
+ });
+ }
+
+ /**
+ * Creates table to display notifications
+ */
+ private void createTable()
+ {
+ _table = _toolkit.createTable(_form.getBody(), SWT.MULTI | SWT.FULL_SELECTION);
+ _table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ TableColumn column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[0]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[1]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[2]);
+ column.setWidth(130);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[3]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[4]);
+ column.setWidth(500);
+
+ _table.setHeaderVisible(true);
+ _table.setLinesVisible(true);
+ }
+
+ /**
+ * Creates JFace viewer for the notifications table
+ */
+ protected void createTableViewer()
+ {
+ createTable();
+ _tableViewer = new TableViewer(_table);
+ //_tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _tableViewer.setUseHashlookup(true);
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setColumnProperties(_tableTitles);
+ /*
+ CellEditor[] cellEditors = new CellEditor[_tableTitles.length];
+ TextCellEditor textEditor = new TextCellEditor(table);
+ cellEditors[0] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[1] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[2] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[3] = textEditor;
+
+ // Assign the cell editors to the viewer
+ _tableViewer.setCellEditors(cellEditors);
+ _tableViewer.setCellModifier(new TableCellModifier());
+ */
+
+ addTableListeners();
+
+ //_tableViewer.addSelectionChangedListener(new );
+
+ //_notificationDetails = new Composite(_tabControl, SWT.BORDER);
+ //_notificationDetails.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ //_tabControl.layout();
+ //viewerComposite.layout();
+ }
+
+ /**
+ * Adds listeners to the viewer for displaying notification details
+ */
+ protected void addTableListeners()
+ {
+ _tableViewer.addDoubleClickListener(new IDoubleClickListener()
+ {
+ Display display = null;
+ Shell shell = null;
+ public void doubleClick(DoubleClickEvent event)
+ {
+ display = Display.getCurrent();
+ shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.RESIZE);
+ shell.setText("Notification");
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ shell.setBounds(x/4, y/4, x/2, y/3);
+ StructuredSelection selection = (StructuredSelection)event.getSelection();
+ createPopupContents((NotificationObject)selection.getFirstElement());
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ //If you create it, you dispose it.
+ shell.dispose();
+ }
+
+ private void createPopupContents(NotificationObject obj)
+ {
+ shell.setLayout(new GridLayout());
+
+ Composite parent = _toolkit.createComposite(shell, SWT.NONE);
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ GridLayout layout = new GridLayout(4, true);
+ parent.setLayout(layout);
+
+ // Object name record
+ Label key = _toolkit.createLabel(parent, COLUMN_OBJ, SWT.TRAIL);
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
+ key.setLayoutData(layoutData);
+ Text value = _toolkit.createText(parent, obj.getSourceName(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ // Sequence no record
+ key = _toolkit.createLabel(parent, COLUMN_SEQ, SWT.TRAIL);
+ layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
+ key.setLayoutData(layoutData);
+ value = _toolkit.createText(parent, ""+obj.getSequenceNo(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ // Time row
+ key = _toolkit.createLabel(parent, COLUMN_TIME, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getTimeStamp(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = _toolkit.createLabel(parent, COLUMN_TYPE, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getType(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = _toolkit.createLabel(parent, COLUMN_MSG, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getMessage(), SWT.MULTI | SWT.WRAP| SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ gridData.heightHint = 100;
+ value.setLayoutData(gridData);
+ }
+ });
+ }
+
+ public void refresh()
+ {
+ _notifications = null;
+ _table.deselectAll();
+ _tableViewer.getTable().clearAll();
+
+ Control[] children = _form.getBody().getChildren();
+ for (int i = 0; i < children.length; i++)
+ {
+ children[i].setVisible(true);
+ }
+
+ workerRunning = true;
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ /**
+ * Content provider class for the table viewer
+ */
+ protected class ContentProviderImpl implements IStructuredContentProvider, INotificationViewer
+ {
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+ public void dispose()
+ {
+
+ }
+ public Object[] getElements(Object parent)
+ {
+ return _notifications.toArray(new NotificationObject[0]);
+ }
+ public void addNotification(NotificationObject notification)
+ {
+ _tableViewer.add(notification);
+ }
+
+ public void addNotification(List<NotificationObject> notificationList)
+ {
+ _tableViewer.add(notificationList.toArray(new NotificationObject[0]));
+ }
+ }
+
+ /**
+ * Label provider for the table viewer
+ */
+ protected class LabelProviderImpl implements ITableLabelProvider
+ {
+ List<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
+ public void addListener(ILabelProviderListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ public void dispose(){
+
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex)
+ {
+ String result = null;
+ NotificationObject t = (NotificationObject)element;
+ switch(columnIndex)
+ {
+ case 0 :
+ result = t.getSourceName();
+ break;
+ case 1 :
+ result = String.valueOf(t.getSequenceNo());
+ break;
+ case 2 :
+ result = String.valueOf(t.getTimeStamp());
+ break;
+ case 3 :
+ result = t.getType();
+ break;
+ case 4 :
+ result = t.getMessage();
+ break;
+ default :
+ result = "";
+ }
+
+ return result;
+ }
+
+ public boolean isLabelProperty(Object element, String property)
+ {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener)
+ {
+ listeners.remove(listener);
+ }
+ } // end of LabelProviderImpl
+
+ protected boolean workerRunning = false;
+ protected void setWorkerRunning(boolean running)
+ {
+ workerRunning = running;
+ }
+
+ /**
+ * Worker class which keeps looking if there are new notifications coming from server for the selected mbean
+ */
+ private class Worker implements Runnable
+ {
+ public void run()
+ {
+ Display display = _tabFolder.getDisplay();
+ while(true)
+ {
+ if (!workerRunning || display == null)
+ {
+ sleep();
+ continue;
+ }
+
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ if (_form == null || _form.isDisposed())
+ return;
+ setWorkerRunning(_form.isVisible());
+ if (!workerRunning) return;
+
+ updateTableViewer();
+ }
+ });
+
+ sleep();
+ }
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch(Exception ex)
+ {
+
+ }
+ }
+ }
+
+ /**
+ * Updates the table with new notifications received from mbean server for all mbeans
+ */
+ protected void updateTableViewer()
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
+ List<NotificationObject> newList = serverRegistry.getNotifications(null);
+ if (newList == null)
+ return;
+
+ _notifications = newList;
+ _tableViewer.setInput(_notifications);
+ _tableViewer.refresh();
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
index 9625a58f20..9b5cddd342 100644
--- a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
@@ -20,8 +20,13 @@
*/
package org.apache.qpid.management.ui.views;
+import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -70,6 +75,8 @@ public class ViewUtility
public static final String PREV = "Previous";
public static final String INDEX = "Index";
+ private static final Comparator tabularDataComparator = new TabularDataComparator();
+
private static List<String> SUPPORTED_ARRAY_DATATYPES = new ArrayList<String>();
static
{
@@ -121,6 +128,9 @@ public class ViewUtility
text.setLayoutData(layoutData);
return;
}
+
+ Collections.sort(list, tabularDataComparator);
+
// Attach the tabular record to be retrieved and shown later when record is traversed
// using first/next/previous/last buttons
composite.setData(list);
@@ -549,4 +559,63 @@ public class ViewUtility
oldControls[i].dispose();
}
}
+
+ public static String getHashedString(Object text) throws NoSuchAlgorithmException, UnsupportedEncodingException
+ {
+ char[] chars = getHash((String)text);
+ return new String(chars);
+ }
+
+ public static char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
+ {
+ byte[] data = text.getBytes("utf-8");
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ for (byte b : data)
+ {
+ md.update(b);
+ }
+
+ byte[] digest = md.digest();
+
+ char[] hash = new char[digest.length ];
+
+ int index = 0;
+ for (byte b : digest)
+ {
+ hash[index++] = (char) b;
+ }
+
+ return hash;
+ }
+
+ private static class TabularDataComparator implements java.util.Comparator<Map.Entry>
+ {
+ public int compare(Map.Entry data1, Map.Entry data2)
+ {
+ if (data1.getKey() instanceof List)
+ {
+ Object obj1 = ((List)data1.getKey()).get(0);
+ Object obj2 = ((List)data2.getKey()).get(0);
+ String str1 = obj1.toString();
+ String str2 = obj2.toString();
+ if (obj1 instanceof String)
+ {
+ return str1.compareTo(str2);
+ }
+
+ try
+ {
+ return Long.valueOf(str1).compareTo(Long.valueOf(str2));
+ }
+ catch (Exception ex)
+ {
+ return -1;
+ }
+ }
+
+ return -1;
+ }
+ }
}
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/sasl/MANIFEST.MF b/qpid/java/management/eclipse-plugin/src/main/resources/sasl/MANIFEST.MF
new file mode 100644
index 0000000000..7a9e5caaaf
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/sasl/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Jmxmp Plug-in
+Bundle-SymbolicName: jmxremote.optional
+Bundle-Version: 1.0.1
+Bundle-ClassPath: .
+Bundle-Vendor:
+Bundle-Localization: plugin
+Export-Package: com.sun.jmx.remote.generic,
+ com.sun.jmx.remote.opt.internal,
+ com.sun.jmx.remote.opt.security,
+ com.sun.jmx.remote.opt.util,
+ com.sun.jmx.remote.profile.sasl,
+ com.sun.jmx.remote.profile.tls,
+ com.sun.jmx.remote.protocol.jmxmp,
+ com.sun.jmx.remote.socket,
+ javax.management.remote.generic,
+ javax.management.remote.jmxmp,
+ javax.management.remote.message
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32/configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/win32/configuration/config.ini
index dbe3f23fe9..1762840aff 100644
--- a/qpid/java/management/eclipse-plugin/src/main/resources/win32/configuration/config.ini
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32/configuration/config.ini
@@ -22,5 +22,5 @@
osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
eclipse.product=org.apache.qpid.management.ui.product
eclipse.application=org.apache.qpid.management.ui.application
-osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.core.runtime@start,com.ibm.icu,org.apache.qpid.management.ui,org.eclipse.core.commands,org.eclipse.core.contenttype,org.eclipse.core.expressions,org.eclipse.core.jobs,org.eclipse.core.runtime.compatibility.auth,org.eclipse.core.runtime.compatibility.registry,org.eclipse.equinox.preferences,org.eclipse.equinox.registry,org.eclipse.help,org.eclipse.jface,org.eclipse.swt,org.eclipse.swt.win32.win32.x86,org.eclipse.ui,org.eclipse.ui.forms,org.eclipse.ui.workbench
+osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.core.runtime@start,com.ibm.icu,org.apache.qpid.management.ui,org.eclipse.core.commands,org.eclipse.core.contenttype,org.eclipse.core.expressions,org.eclipse.core.jobs,org.eclipse.core.runtime.compatibility.auth,org.eclipse.core.runtime.compatibility.registry,org.eclipse.equinox.preferences,org.eclipse.equinox.registry,org.eclipse.help,org.eclipse.jface,org.eclipse.swt,org.eclipse.swt.win32.win32.x86,org.eclipse.ui,org.eclipse.ui.forms,jmxremote.optional,org.eclipse.ui.workbench
osgi.bundles.defaultStartLevel=4
diff --git a/qpid/java/perftests/etc/scripts/BDB-Qpid-4.sh b/qpid/java/perftests/etc/scripts/BDB-Qpid-4.sh
new file mode 100755
index 0000000000..f54c057640
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/BDB-Qpid-4.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+if [ -z QPID_HOME ] ; then
+
+echo "QPID_HOME must be set"
+exit 0
+fi
+
+configs=`pwd`
+
+pushd $QPID_HOME/bin/
+
+echo "Starting qpid server - device config"
+./qpid-server -c $configs/bdb-qpid-4/device.xml
+
+echo "Starting qpid server - filepath config"
+./qpid-server -c $configs/bdb-qpid-4/filepath.xml
+
+echo "Starting qpid server - none existent path config"
+./qpid-server -c $configs/bdb-qpid-4/noneexistantpath.xml
+
+echo "Starting qpid server - no permission config"
+./qpid-server -c $configs/bdb-qpid-4/nopermission.xml
+
+echo "Starting qpid server - Star in path config"
+./qpid-server -c $configs/bdb-qpid-4/starpath.xml
+
+popd
diff --git a/qpid/java/perftests/etc/scripts/BDB-Qpid.sh b/qpid/java/perftests/etc/scripts/BDB-Qpid.sh
new file mode 100755
index 0000000000..8ff233dc6d
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/BDB-Qpid.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Parse arguements taking all - prefixed args as JAVA_OPTS
+for arg in "$@"; do
+ if [[ $arg == -java:* ]]; then
+ JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
+ else
+ ARGS="${ARGS}$arg "
+ fi
+done
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx256m -Dbadger.level=warn -Damqj.test.logging.level=warn -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar org.apache.qpid.ping.PingDurableClient -o $QPID_WORK/results ${ARGS}
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-1.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-1.sh
new file mode 100755
index 0000000000..518b06aac4
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-1.sh
@@ -0,0 +1 @@
+./PQ-Qpid-1.sh $@ & ./PQ-Qpid-1-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-2.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-2.sh
new file mode 100755
index 0000000000..bbe5d75cd3
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-2.sh
@@ -0,0 +1 @@
+./PQ-Qpid-2.sh $@ & ./PQ-Qpid-2-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-3.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-3.sh
new file mode 100755
index 0000000000..7e9430c8a3
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-3.sh
@@ -0,0 +1 @@
+./PQ-Qpid-3.sh $@ & ./PQ-Qpid-3-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-4.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-4.sh
new file mode 100755
index 0000000000..720ca35fe1
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-4.sh
@@ -0,0 +1 @@
+./PQ-Qpid-4.sh $@ & ./PQ-Qpid-4-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-5.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-5.sh
new file mode 100755
index 0000000000..fe19f6a513
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-5.sh
@@ -0,0 +1 @@
+./PQ-Qpid-5.sh $@ & ./PQ-Qpid-5-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/CTQ-Qpid-6.sh b/qpid/java/perftests/etc/scripts/CTQ-Qpid-6.sh
new file mode 100755
index 0000000000..09df5ce25a
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/CTQ-Qpid-6.sh
@@ -0,0 +1 @@
+./PQ-Qpid-6.sh $@ & ./PQ-Qpid-6-P.sh $@
diff --git a/qpid/java/perftests/etc/scripts/PT-Qpid-13.sh b/qpid/java/perftests/etc/scripts/PT-Qpid-13.sh
new file mode 100755
index 0000000000..630aa22ca3
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/PT-Qpid-13.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Parse arguements taking all - prefixed args as JAVA_OPTS
+for arg in "$@"; do
+ if [[ $arg == -java:* ]]; then
+ JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
+ else
+ ARGS="${ARGS}$arg "
+ fi
+done
+
+echo "Starting 6 parallel tests"
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.1 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=newd1 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.2 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=newd2 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.3 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=newd3 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.4 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinatioNname=newd4 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.5 -s [250] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=newd5 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-13.6 -s [250] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=newd6 uniqueDests=true batchSize=250 transacted=true commitBatchSize=50 -o $QPID_WORK/results ${ARGS}
+
diff --git a/qpid/java/perftests/etc/scripts/PT-Qpid-14.sh b/qpid/java/perftests/etc/scripts/PT-Qpid-14.sh
new file mode 100755
index 0000000000..7499eedda4
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/PT-Qpid-14.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# Parse arguements taking all - prefixed args as JAVA_OPTS
+for arg in "$@"; do
+ if [[ $arg == -java:* ]]; then
+ JAVA_OPTS="${JAVA_OPTS}-`echo $arg|cut -d ':' -f 2` "
+ else
+ ARGS="${ARGS}$arg "
+ fi
+done
+echo "Starting 6 parallel tests"
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=ping1 batchSize=250 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=ping2 batchSize=250 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=ping3 batchSize=250 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[200] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256destinationname=ping4 batchSize=250 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=ping5 batchSize=250 -o $QPID_WORK/results ${ARGS} &
+
+java -Xms256m -Dlog4j.configuration=perftests.log4j -Xmx3072m -Dbadger.level=warn -Damqj.test.logging.level=info -Damqj.logging.level=warn ${JAVA_OPTS} -cp qpid-perftests-1.0-incubating-M2-SNAPSHOT-all-test-deps.jar uk.co.thebadgerset.junit.extensions.TKTestRunner -n PT-Qpid-14 -s [250] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationName=ping6 batchSize=250 -o $QPID_WORK/results ${ARGS}
diff --git a/qpid/java/perftests/etc/scripts/bdb-qpid-4/device.xml b/qpid/java/perftests/etc/scripts/bdb-qpid-4/device.xml
new file mode 100644
index 0000000000..a052f85167
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/bdb-qpid-4/device.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <userhome>$HOME</userhome>
+ <connector>
+ <!-- Uncomment out this block and edit the keystorePath and keystorePassword
+ to enable SSL support
+ <ssl>
+ <enabled>true</enabled>
+ <sslOnly>true</sslOnly>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
+ </ssl>-->
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>device</name>
+ <device>
+ <store>
+ <!-- /dev/null give it a device -->
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>/dev/null</environment-path>
+ </store>
+ </device>
+ </virtualhost>
+
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/perftests/etc/scripts/bdb-qpid-4/filepath.xml b/qpid/java/perftests/etc/scripts/bdb-qpid-4/filepath.xml
new file mode 100644
index 0000000000..ebce10cb95
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/bdb-qpid-4/filepath.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <userhome>$HOME</userhome>
+ <connector>
+ <!-- Uncomment out this block and edit the keystorePath and keystorePassword
+ to enable SSL support
+ <ssl>
+ <enabled>true</enabled>
+ <sslOnly>true</sslOnly>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
+ </ssl>-->
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>pathToAFile</name>
+ <pathToAFile>
+ <store>
+ <!-- ${conf}/config.xml give the path to a file -->
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${conf}/config.xml</environment-path>
+ </store>
+ </pathToAFile>
+ </virtualhost>
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/perftests/etc/scripts/bdb-qpid-4/noneexistantpath.xml b/qpid/java/perftests/etc/scripts/bdb-qpid-4/noneexistantpath.xml
new file mode 100644
index 0000000000..c20beb1c92
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/bdb-qpid-4/noneexistantpath.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <userhome>$HOME</userhome>
+ <connector>
+ <!-- Uncomment out this block and edit the keystorePath and keystorePassword
+ to enable SSL support
+ <ssl>
+ <enabled>true</enabled>
+ <sslOnly>true</sslOnly>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
+ </ssl>-->
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>nonExistentPath</name>
+ <nonExistentPath>
+ <store>
+ <!-- Path to a location that doesn't exist -->
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdb-qpid-5/1/localhost-store</environment-path>
+ </store>
+ </nonExistentPath>
+ </virtualhost>
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/perftests/etc/scripts/bdb-qpid-4/nopermission.xml b/qpid/java/perftests/etc/scripts/bdb-qpid-4/nopermission.xml
new file mode 100644
index 0000000000..958a19cda2
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/bdb-qpid-4/nopermission.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <userhome>$HOME</userhome>
+ <connector>
+ <!-- Uncomment out this block and edit the keystorePath and keystorePassword
+ to enable SSL support
+ <ssl>
+ <enabled>true</enabled>
+ <sslOnly>true</sslOnly>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
+ </ssl>-->
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ </security>
+
+ <virtualhosts>
+ <virtualhost>
+ <name>noPermissions</name>
+ <noPermissions>
+ <store>
+ <!-- /etc/bdb-qpid-5 give it somewhere it doesn't have permission -->
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>/etc/bdb-qpid-5/</environment-path>
+ </store>
+ </noPermissions>
+ </virtualhost>
+
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/perftests/etc/scripts/bdb-qpid-4/starpath.xml b/qpid/java/perftests/etc/scripts/bdb-qpid-4/starpath.xml
new file mode 100644
index 0000000000..c795ec5202
--- /dev/null
+++ b/qpid/java/perftests/etc/scripts/bdb-qpid-4/starpath.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements. See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership. The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License. You may obtain a copy of the License at
+ -
+ - http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied. See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<broker>
+ <prefix>${QPID_HOME}</prefix>
+ <work>${QPID_WORK}</work>
+ <conf>${prefix}/etc</conf>
+ <userhome>$HOME</userhome>
+ <connector>
+ <!-- Uncomment out this block and edit the keystorePath and keystorePassword
+ to enable SSL support
+ <ssl>
+ <enabled>true</enabled>
+ <sslOnly>true</sslOnly>
+ <keystorePath>/path/to/keystore.ks</keystorePath>
+ <keystorePassword>keystorepass</keystorePassword>
+ </ssl>-->
+ <qpidnio>true</qpidnio>
+ <transport>nio</transport>
+ <port>5672</port>
+ <sslport>8672</sslport>
+ <socketReceiveBuffer>32768</socketReceiveBuffer>
+ <socketSendBuffer>32768</socketSendBuffer>
+ </connector>
+ <management>
+ <enabled>true</enabled>
+ </management>
+ <advanced>
+ <filterchain enableExecutorPool="true"/>
+ <enablePooledAllocator>false</enablePooledAllocator>
+ <enableDirectBuffers>false</enableDirectBuffers>
+ <framesize>65535</framesize>
+ <compressBufferOnQueue>false</compressBufferOnQueue>
+ </advanced>
+
+ <security>
+ <principal-databases>
+ <principal-database>
+ <name>passwordfile</name>
+ <class>org.apache.qpid.server.security.auth.database.PlainPasswordVhostFilePrincipalDatabase</class>
+ <attributes>
+ <attribute>
+ <name>passwordFile</name>
+ <value>${conf}/passwdVhost</value>
+ </attribute>
+ </attributes>
+ </principal-database>
+ </principal-databases>
+
+ <access>
+ <class>org.apache.qpid.server.security.access.AllowAll</class>
+ </access>
+ </security>
+
+ <virtualhosts>
+
+ <virtualhost>
+ <name>pathWithStar</name>
+ <pathWithStar>
+ <store>
+ <!-- ${work}/bdbd-qpid-5/2/* have a * in path-->
+ <class>org.apache.qpid.server.store.berkeleydb.BDBMessageStore</class>
+ <environment-path>${work}/bdb-qpid-5/2/*-store</environment-path>
+ </store>
+ </pathWithStar>
+ </virtualhost>
+
+ </virtualhosts>
+ <heartbeat>
+ <delay>0</delay>
+ <timeoutFactor>2.0</timeoutFactor>
+ </heartbeat>
+ <queue>
+ <auto_register>true</auto_register>
+ </queue>
+
+ <virtualhosts>${conf}/virtualhosts.xml</virtualhosts>
+</broker>
+
+
diff --git a/qpid/java/perftests/pom.xml b/qpid/java/perftests/pom.xml
index c09d6a5a75..63edac1801 100644
--- a/qpid/java/perftests/pom.xml
+++ b/qpid/java/perftests/pom.xml
@@ -40,6 +40,18 @@
</properties>
<!-- Temporary local maven repo, whilst JUnit Toolkit is still reaching stable version to add to central maven repository. -->
+ <repositories>
+ <repository>
+ <id>junit-toolkit.snapshots</id>
+ <name>JUnit Toolkit SNAPSHOT Repository</name>
+ <url>http://junit-toolkit.svn.sourceforge.net/svnroot/junit-toolkit/snapshots/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <!-- Temporary local maven repo, whilst JUnit Toolkit is still reaching stable version to add to central maven repository. -->
<pluginRepositories>
<pluginRepository>
<id>junit-toolkit-plugin.snapshots</id>
@@ -86,18 +98,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
<!-- The JUnit Toolkit maven2 plugin is in the process of being added to the maven repository.
@@ -130,9 +130,16 @@
<configuration>
<scriptOutDirectory>target</scriptOutDirectory>
<testJar>${project.build.finalName}-all-test-deps.jar</testJar>
-
<systemproperties>
<property>
+ <name>-Xms</name>
+ <value>256m</value>
+ </property>
+ <property>
+ <name>-Xmx</name>
+ <value>3072m</value>
+ </property>
+ <property>
<name>log4j.configuration</name>
<value>${log4j.perftests}</value>
</property>
@@ -185,6 +192,267 @@
<Ping-Failover-After-Commit>
-n Ping-Failover-After-Commit -s [100] -o . -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=10 failAfterCommit=true
</Ping-Failover-After-Commit>
+
+ <!-- P2P Volume Tests. -->
+ <VT-Qpid-1>-n VT-Qpid-1 -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 transacted=true -o $QPID_WORK/results</VT-Qpid-1>
+ <VT-Qpid-2>-n VT-Qpid-2 -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=256 -o $QPID_WORK/results</VT-Qpid-2>
+ <!-- Setting sample to 3,000,000 will result in a log entry every 10 minutes so should have 144 data points for the run. -->
+ <VT-Qpid-3>-n VT-Qpid-3 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true rate=10000 messageSize=256 transacted=true -o $QPID_WORK/results commitBatchSize=100 batchSize=10000</VT-Qpid-3>
+ <VT-Qpid-4>-n VT-Qpid-4 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true rate=10000 messageSize=256 -o $QPID_WORK/results batchSize=10000</VT-Qpid-4>
+ <VT-Qpid-5>-n VT-Qpid-5 -s[1000] -c[1,32],samples=32 -d2M transacted=true commitBatchSize=100 persistent=false rate=1000 messageSize=256</VT-Qpid-5>
+ <VT-Qpid-6>-n VT-Qpid-6 -s[100] -c[1,32],samples=32 -d2M transacted=true commitBatchSize=100 persistent=true rate=100 messageSize=256</VT-Qpid-6>
+
+ <!-- P2P Scalability Tests. -->
+ <!-- 250,000 Total, 1P-1T-1C -->
+ <PT-Qpid-1>-n PT-Qpid-1 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results commitBatchSize=100 transacted=true</PT-Qpid-1>
+ <PT-Qpid-2>-n PT-Qpid-2 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-2>
+
+ <!-- 25000 Msgs * 10 Brokers = 250,000 Total, 10P-1Q-10C -->
+ <PT-Qpid-3>-n PT-Qpid-3 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results commitBatchSize=100 transacted=true</PT-Qpid-3>
+ <PT-Qpid-4>-n PT-Qpid-4 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-4>
+
+ <!-- 25000 Msgs * 10 Brokers = 250,000 Tota,l 10P-10T-10C 10*(1P-1Q-1C) -->
+ <PT-Qpid-5>-n PT-Qpid-5 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results transacted=true commitBatchSize=100</PT-Qpid-5>
+ <PT-Qpid-6>-n PT-Qpid-6 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-6>
+
+ <!-- 2500 Msgs * 10 Brokers * 10 Topics/Clients = 250,000 Total, 10P-100T-10C 10*(1P-10T-1C) -->
+ <PT-Qpid-7>-n PT-Qpid-7 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true destinationsCount=10 transacted=true commitBatchSize=100 messageSize=256 -o $QPID_WORK/results</PT-Qpid-7>
+ <PT-Qpid-8>-n PT-Qpid-8 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true destinationsCount=10 messageSize=256 -o $QPID_WORK/results</PT-Qpid-8>
+
+ <!-- 2500 Msgs * 100 Brokers = 250,000 Total, 100P-100T-100C 100*(1P-1T-1C) -->
+ <PT-Qpid-9>-n PT-Qpid-9 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</PT-Qpid-9>
+ <PT-Qpid-10>-n PT-Qpid-10 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 batchSize=250 -o $QPID_WORK/results</PT-Qpid-10>
+
+ <!-- 250 Msgs * 100 Brokers * 10 Clients = 250,000 Total, 100P-1000T-100C 100*(1P-10T-1C) -->
+ <PT-Qpid-11>-n PT-Qpid-11 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationsCount=10 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-11>
+ <PT-Qpid-12>-n PT-Qpid-12 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 destinationsCount=10 -o $QPID_WORK/results</PT-Qpid-12>
+
+ <!-- 250 Msgs * 1000 Brokers = 250,000 Total, 1000P-1000T-1000C 1000*(1P-1T-1C) -->
+ <!-- PT-Qpid-13>-n PT-Qpid-13 -s [100] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 batchSize=100 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-13 -->
+ <!-- PT-Qpid-14>-n PT-Qpid-14 -s [100] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=256 batchSize=100 -o $QPID_WORK/results</PT-Qpid-14 -->
+
+ <!-- P2P Volume Tests. -->
+ <VQ-Qpid-1>-n VQ-Qpid-1 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</VQ-Qpid-1>
+ <VQ-Qpid-2>-n VQ-Qpid-2 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 commitBatchSize=100 -o $QPID_WORK/results</VQ-Qpid-2>
+ <!-- Setting sample to 3,000,000 will result in a log entry every 10 minutes so should have 144 data points for the run. -->
+ <VQ-Qpid-3>-n VQ-Qpid-3 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf rate=10000 messageSize=256 commitBatchSize=100 transacted=true batchSize=100000 -o $QPID_WORK/results</VQ-Qpid-3>
+ <VQ-Qpid-4>-n VQ-Qpid-4 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf rate=10000 messageSize=256 batchSize=100000 -o $QPID_WORK/results</VQ-Qpid-4>
+
+ <!-- P2P Scalability Tests. -->
+ <!-- 15,000 Total, 1P-1Q-1C -->
+ <PQ-Qpid-1>-n PQ-Qpid-1 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf transacted=true commitBatchSize=100 messageSize=256 -o $QPID_WORK/results</PQ-Qpid-1>
+ <PQ-Qpid-2>-n PQ-Qpid-2 -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 -o $QPID_WORK/results</PQ-Qpid-2>
+
+ <!-- 1500 Messages * 10 Brokers = 15,000 Total, 10P-1Q-10C -->
+ <PQ-Qpid-3>-n PQ-Qpid-3 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 destinationName=ping transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-3>
+ <PQ-Qpid-4>-n PQ-Qpid-4 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 destinationName=ping -o $QPID_WORK/results</PQ-Qpid-4>
+
+ <!-- 1500 Messages * 10 Brokers = 15,000 Total, 10P-10Q-10C 10*(1P-1Q-1C) -->
+ <PQ-Qpid-5>-n PQ-Qpid-5 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-5>
+ <PQ-Qpid-6>-n PQ-Qpid-6 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 -o $QPID_WORK/results</PQ-Qpid-6>
+
+ <!-- 1500 Messages * 10 Brokers = 15,000 Total, 10P-100Q-10C 10*(1P-10Q-1C) -->
+ <PQ-Qpid-7>-n PQ-Qpid-7 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 commitBatchSize=100 destinationsCount=10 transacted=true -o $QPID_WORK/results</PQ-Qpid-7>
+ <PQ-Qpid-8>-n PQ-Qpid-8 -d 10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 destinationsCount=10 -o $QPID_WORK/results</PQ-Qpid-8>
+
+ <!-- 150 Messages * 100 Brokers = 15,000 Total, 100P-100Q-100C 100*(1P-1Q-1C) -->
+ <PQ-Qpid-9>-n PQ-Qpid-9 -d 20M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-9>
+ <PQ-Qpid-10>-n PQ-Qpid-10 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 -o $QPID_WORK/results</PQ-Qpid-10>
+
+
+ <!-- 150 Messages * 100 Brokers = 15,000 Total, 100P-1000Q-100C 100*(1P-10Q-1C) -->
+ <PQ-Qpid-11>-n PQ-Qpid-11 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 destinationsCount=10 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-11>
+ <PQ-Qpid-12>-n PQ-Qpid-12 -d 10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 destinationsCount=10 -o $QPID_WORK/results</PQ-Qpid-12>
+
+ <!-- 15 Messages * 1000 Brokers = 15,000 Total, 1000P-1000Q-1000C 1000*(1P-1Q-1C) -->
+ <!--PQ-Qpid-13>-n PQ-Qpid-13 -d 10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-13>
+ <PQ-Qpid-14>-n PQ-Qpid-14 -d 10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=15 -o $QPID_WORK/results</PQ-Qpid-14-->
+
+ <!-- Increasing Message Payload Tests. -->
+ <!-- Topic Testing -->
+ <LT-Qpid-1-512b>-n LT-Qpid-1-512b -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=512 transacted=true commitBatchSize=100 -o $QPID_WORK/results</LT-Qpid-1-512b>
+ <LT-Qpid-2-512b>-n LT-Qpid-2-512b -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=512 -o $QPID_WORK/results</LT-Qpid-2-512b>
+
+ <LT-Qpid-1-1K>-n LT-Qpid-1-1K -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 transacted=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-1-1K>
+ <LT-Qpid-2-1K>-n LT-Qpid-2-1K -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-2-1K>
+
+ <LT-Qpid-1-5K>-n LT-Qpid-1-5K -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=5120 transacted=true -o $QPID_WORK/results</LT-Qpid-1-5K>
+ <LT-Qpid-2-5K>-n LT-Qpid-2-5K -d 10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=5120 -o $QPID_WORK/results</LT-Qpid-2-5K>
+
+ <LT-Qpid-1-10K>-n LT-Qpid-1-10K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=10240 transacted=true -o $QPID_WORK/results</LT-Qpid-1-10K>
+ <LT-Qpid-2-10K>-n LT-Qpid-2-10K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=10240 -o $QPID_WORK/results</LT-Qpid-2-10K>
+
+ <LT-Qpid-1-50K>-n LT-Qpid-1-50K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=51200 transacted=true -o $QPID_WORK/results</LT-Qpid-1-50K>
+ <LT-Qpid-2-50K>-n LT-Qpid-2-50K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=51200 -o $QPID_WORK/results</LT-Qpid-2-50K>
+
+ <LT-Qpid-1-100K>-n LT-Qpid-1-100K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=102400 transacted=true -o $QPID_WORK/results</LT-Qpid-1-100K>
+ <LT-Qpid-2-100K>-n LT-Qpid-2-100K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=102400 -o $QPID_WORK/results</LT-Qpid-2-100K>
+
+ <LT-Qpid-1-1M>-n LT-Qpid-1-1M -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true commitBatchSize=100 messageSize=1048576 transacted=true -o $QPID_WORK/results</LT-Qpid-1-1M>
+ <LT-Qpid-2-1M>-n LT-Qpid-2-1M -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf pubsub=true messageSize=1048476 -o $QPID_WORK/results</LT-Qpid-2-1M>
+
+ <!-- Queue Testing -->
+ <LT-Qpid-3-512b>-n LT-Qpid-3-512b -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=512 transacted=true -o $QPID_WORK/results</LT-Qpid-3-512b>
+ <LT-Qpid-4-512b>-n LT-Qpid-4-512b -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=512 -o $QPID_WORK/results</LT-Qpid-4-512b>
+
+ <LT-Qpid-3-1K>-n LT-Qpid-3-1K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=1024 transacted=true -o $QPID_WORK/results</LT-Qpid-3-1K>
+ <LT-Qpid-4-1K>-n LT-Qpid-4-1K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPer messageSize=1024 -o $QPID_WORK/results</LT-Qpid-4-1K>
+
+ <LT-Qpid-3-5K>-n LT-Qpid-3-5K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=5120 transacted=true -o $QPID_WORK/results</LT-Qpid-3-5K>
+ <LT-Qpid-4-5K>-n LT-Qpid-4-5K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=5120 -o $QPID_WORK/results</LT-Qpid-4-5K>
+
+ <LT-Qpid-3-10K>-n LT-Qpid-3-10K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=10240 transacted=true -o $QPID_WORK/results</LT-Qpid-3-10K>
+ <LT-Qpid-4-10K>-n LT-Qpid-4-10K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=10240 -o $QPID_WORK/results</LT-Qpid-4-10K>
+
+ <LT-Qpid-3-50K>-n LT-Qpid-3-50K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=51200 transacted=true -o $QPID_WORK/results</LT-Qpid-3-50K>
+ <LT-Qpid-4-50K>-n LT-Qpid-4-50K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=51200 -o $QPID_WORK/results</LT-Qpid-4-50K>
+
+ <LT-Qpid-3-100K>-n LT-Qpid-3-100K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=102400 transacted=true -o $QPID_WORK/results</LT-Qpid-3-100K>
+ <LT-Qpid-4-100K>-n LT-Qpid-4-100K -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=102400 -o $QPID_WORK/results</LT-Qpid-4-100K>
+
+ <LT-Qpid-3-1M>-n LT-Qpid-3-1M -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf commitBatchSize=100 messageSize=1048576 transacted=true -o $QPID_WORK/results</LT-Qpid-3-1M>
+ <LT-Qpid-4-1M>-n LT-Qpid-4-1M -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=1048576 -o $QPID_WORK/results</LT-Qpid-4-1M>
+
+ <!-- Failover Tests. -->
+ <!-- Transactional -->
+ <FT-Qpid-1>-n FT-Qpid-1 -s [250000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" FailBeforeSend=true -o $QPID_WORK/results</FT-Qpid-1>
+ <FT-Qpid-2>-n FT-Qpid-2 -s [250000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" failAfterSend=true -o $QPID_WORK/results</FT-Qpid-2>
+ <FT-Qpid-3>-n FT-Qpid-3 -s [250000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" failAfterCommit=true -o $QPID_WORK/results</FT-Qpid-3>
+
+ <!-- Non Transactional -->
+ <FT-Qpid-4>-n FT-Qpid-4 -s [250000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=10000 broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" transacted=false failBeforeSend=true -o $QPID_WORK/results</FT-Qpid-4>
+ <FT-Qpid-5>-n FT-Qpid-5 -s [250000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf messageSize=256 batchSize=10000 broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" transacted=false failAfterSend=true -o $QPID_WORK/results</FT-Qpid-5>
+
+
+ <!-- Persistent Tests -->
+
+ <!-- P2P Volume Tests. -->
+ <VT-Qpid-1-P>-n VT-Qpid-1 -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</VT-Qpid-1-P>
+ <VT-Qpid-2-P>-n VT-Qpid-2 -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 -o $QPID_WORK/results</VT-Qpid-2-P>
+ <!-- Setting sample to 3,000,000 will result in a log entry every 10 minutes so should have 144 data points for the run. -->
+ <VT-Qpid-3-P>-n VT-Qpid-3 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true rate=1000 messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results batchSize=10000</VT-Qpid-3-P>
+ <VT-Qpid-4-P>-n VT-Qpid-4 -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true rate=1000 messageSize=256 -o $QPID_WORK/results batchSize=10000</VT-Qpid-4-P>
+
+ <!-- P2P Scalability Tests. -->
+ <!-- 25,000 Total, 1P-1T-1C -->
+ <PT-Qpid-1-P>-n PT-Qpid-1-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</PT-Qpid-1-P>
+ <PT-Qpid-2-P>-n PT-Qpid-2-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-2-P>
+
+ <!-- 2500 Msgs * 10 Brokers = 25,000 Total, 10P-1Q-10C -->
+ <PT-Qpid-3-P>-n PT-Qpid-3-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</PT-Qpid-3-P>
+ <PT-Qpid-4-P>-n PT-Qpid-4-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-4-P>
+
+ <!-- 2500 Msgs * 10 Brokers = 25,000 Tota,l 10P-10T-10C 10*(1P-1Q-1C) -->
+ <PT-Qpid-5-P>-n PT-Qpid-5-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true transacted=true messageSize=256 commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-5-P>
+ <PT-Qpid-6-P>-n PT-Qpid-6-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-6-P>
+
+ <!-- 250 Msgs * 10 Brokers * 10 Topics/Clients = 250,000 Total, 10P-100T-10C 10*(1P-10T-1C) -->
+ <PT-Qpid-7-P>-n PT-Qpid-7-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true destinationsCount=10 transacted=true messageSize=256 commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-7-P>
+ <PT-Qpid-8-P>-n PT-Qpid-8-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true destinationsCount=10 messageSize=256 -o $QPID_WORK/results</PT-Qpid-8-P>
+
+ <!-- 250 Msgs * 100 Brokers = 25,000 Total, 100P-100T-100C 100*(1P-1T-1C) -->
+ <PT-Qpid-9-P>-n PT-Qpid-9-P -d10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</PT-Qpid-9-P>
+ <PT-Qpid-10-P>-n PT-Qpid-10-P -d10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 batchSize=250 -o $QPID_WORK/results</PT-Qpid-10-P>
+
+ <!-- 25 Msgs * 100 Brokers * 10 Clients = 250,000 Total, 100P-1000T-100C 100*(1P-10T-1C) -->
+ <PT-Qpid-11-P>-n PT-Qpid-11-P -d10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 destinationsCount=10 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-11-P>
+ <PT-Qpid-12-P>-n PT-Qpid-12-P -d10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 destinationsCount=10 -o $QPID_WORK/results</PT-Qpid-12-P>
+
+ <!-- 25 Msgs * 1000 Brokers = 25,000 Total, 1000P-1000T-1000C 1000*(1P-1T-1C) -->
+ <!--PT-Qpid-13-P>-n PT-Qpid-13-P -d10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PT-Qpid-13-P-->
+ <!--PT-Qpid-14-P>-n PT-Qpid-14-P -d10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=256 -o $QPID_WORK/results</PT-Qpid-14-P-->
+
+ <!-- P2P Volume Tests. -->
+ <VQ-Qpid-1-P>-n VQ-Qpid-1-P -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results</VQ-Qpid-1-P>
+ <VQ-Qpid-2-P>-n VQ-Qpid-2-P -d1H -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 -o $QPID_WORK/results</VQ-Qpid-2-P>
+ <!-- Setting sample to 3,000,000 will result in a log entry every 10 minutes so should have 144 data points for the run. -->
+ <VQ-Qpid-3-P>-n VQ-Qpid-3-P -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true rate=10000 messageSize=256 commitBatchSize=100 transacted=true -o $QPID_WORK/results batchSize=100000</VQ-Qpid-3-P>
+ <VQ-Qpid-4-P>-n VQ-Qpid-4-P -s [100000] -d 24H -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true rate=10000 messageSize=256 -o $QPID_WORK/results batchSize=100000</VQ-Qpid-4-P>
+
+ <!-- P2P Scalability Tests. -->
+ <!-- 1500 Total, 1P-1Q-1C -->
+ <PQ-Qpid-1-P>-n PQ-Qpid-1-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true transacted=true commitBatchSize=100 messageSize=256 -o $QPID_WORK/results</PQ-Qpid-1-P>
+ <PQ-Qpid-2-P>-n PQ-Qpid-2-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 -o $QPID_WORK/results</PQ-Qpid-2-P>
+
+ <!-- 150 Messages * 10 Brokers = 15,000 Total, 10P-1Q-10C -->
+ <PQ-Qpid-3-P>-n PQ-Qpid-3-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 destinationName=ping transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-3-P>
+ <PQ-Qpid-4-P>-n PQ-Qpid-4-P -d10M -s [100] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 destinationName=ping -o $QPID_WORK/results</PQ-Qpid-4-P>
+
+ <!-- 150 Messages * 10 Brokers = 15,000 Total, 10P-10Q-10C 10*(1P-1Q-1C) -->
+ <PQ-Qpid-5-P>-n PQ-Qpid-5-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-5-P>
+ <PQ-Qpid-6-P>-n PQ-Qpid-6-P -d10M -s [100] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 -o $QPID_WORK/results</PQ-Qpid-6-P>
+
+ <!-- 150 Messages * 10 Brokers = 15,000 Total, 10P-100Q-10C 10*(1P-10Q-1C) -->
+ <PQ-Qpid-7-P>-n PQ-Qpid-7-P -d10M -s [1000] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 batchSize=100 destinationsCount=10 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-7-P>
+ <PQ-Qpid-8-P>-n PQ-Qpid-8-P -d10M -s [100] -c[10] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 destinationsCount=10 -o $QPID_WORK/results rate=200</PQ-Qpid-8-P>
+
+ <!-- 15 Messages * 100 Brokers = 15,000 Total, 100P-100Q-100C 100*(1P-1Q-1C) -->
+ <PQ-Qpid-9-P>-n PQ-Qpid-9-P -d10M -s [1000] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 batchSize=50 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-9-P>
+ <PQ-Qpid-10-P>-n PQ-Qpid-10-P -d10M -s [100] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 -o $QPID_WORK/results</PQ-Qpid-10-P>
+
+ <!-- 15 Messages * 100 Brokers = 15,000 Total, 100P-1000Q-100C 100*(1P-10Q-1C) -->
+ <PQ-Qpid-11-P>-n PQ-Qpid-11-P -d10M -s [100] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 destinationsCount=10 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-11-P>
+ <PQ-Qpid-12-P>-n PQ-Qpid-12-P -d10M -s [100] -c[100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 destinationsCount=10 -o $QPID_WORK/results</PQ-Qpid-12-P>
+
+ <!-- 2 Messages * 1000 Brokers = 2,000 Total, 1000P-1000Q-1000C 1000*(1P-1Q-1C) -->
+ <!--PQ-Qpid-13-P>-n PQ-Qpid-13-P -d10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 transacted=true commitBatchSize=100 -o $QPID_WORK/results</PQ-Qpid-13-P>
+ <PQ-Qpid-14-P>-n PQ-Qpid-14-P -d10M -s [1000] -c[1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 -o $QPID_WORK/results</PQ-Qpid-14-P-->
+
+ <!-- Increasing Message Payload Tests. -->
+ <!-- Topic Testing -->
+ <LT-Qpid-1-512b-P>-n LT-Qpid-1-512b-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=512 transacted=true commitBatchSize=100 -o $QPID_WORK/results</LT-Qpid-1-512b-P>
+ <LT-Qpid-2-512b-P>-n LT-Qpid-2-512b-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=512 -o $QPID_WORK/results</LT-Qpid-2-512b-P>
+
+ <LT-Qpid-1-1K-P>-n LT-Qpid-1-1K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true commitBatchSize=100 transacted=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-1-1K-P>
+ <LT-Qpid-2-1K-P>-n LT-Qpid-2-1K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-2-1K-P>
+
+ <LT-Qpid-1-5K-P>-n LT-Qpid-1-5K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=5120 transacted=true -o $QPID_WORK/results</LT-Qpid-1-5K-P>
+ <LT-Qpid-2-5K-P>-n LT-Qpid-2-5K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=5120 -o $QPID_WORK/results</LT-Qpid-2-5K-P>
+
+ <LT-Qpid-1-10K-P>-n LT-Qpid-1-10K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true commitBatchSize=100 messageSize=10240 transacted=true -o $QPID_WORK/results</LT-Qpid-1-10K-P>
+ <LT-Qpid-2-10K-P>-n LT-Qpid-2-10K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=10240 -o $QPID_WORK/results</LT-Qpid-2-10K-P>
+
+ <LT-Qpid-1-50K-P>-n LT-Qpid-1-50K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=51200 commitBatchSize=100 transacted=true -o $QPID_WORK/results</LT-Qpid-1-50K-P>
+ <LT-Qpid-2-50K-P>-n LT-Qpid-2-50K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=51200 -o $QPID_WORK/results</LT-Qpid-2-50K-P>
+
+ <LT-Qpid-1-100K-P>-n LT-Qpid-1-100K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true commitBatchSize=100 messageSize=102400 transacted=true -o $QPID_WORK/results</LT-Qpid-1-100K-P>
+ <LT-Qpid-2-100K-P>-n LT-Qpid-2-100K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=102400 -o $QPID_WORK/results</LT-Qpid-2-100K-P>
+
+ <LT-Qpid-1-1M-P>-n LT-Qpid-1-1M-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true commitBatchSize=100 messageSize=1048576 transacted=true -o $QPID_WORK/results</LT-Qpid-1-1M-P>
+ <LT-Qpid-2-1M-P>-n LT-Qpid-2-1M-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true pubsub=true messageSize=1048476 -o $QPID_WORK/results</LT-Qpid-2-1M-P>
+
+ <!-- Queue Testing -->
+ <LT-Qpid-3-512b-P>-n LT-Qpid-3-512b-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=512 transacted=true -o $QPID_WORK/results</LT-Qpid-3-512b-P>
+ <LT-Qpid-4-512b-P>-n LT-Qpid-4-512b-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=512 -o $QPID_WORK/results</LT-Qpid-4-512b-P>
+
+ <LT-Qpid-3-1K-P>-n LT-Qpid-3-1K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 transacted=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-3-1K-P>
+ <LT-Qpid-4-1K-P>-n LT-Qpid-4-1K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=1024 -o $QPID_WORK/results</LT-Qpid-4-1K-P>
+
+ <LT-Qpid-3-5K-P>-n LT-Qpid-3-5K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=5120 transacted=true -o $QPID_WORK/results</LT-Qpid-3-5K-P>
+ <LT-Qpid-4-5K-P>-n LT-Qpid-4-5K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=5120 -o $QPID_WORK/results</LT-Qpid-4-5K-P>
+
+ <LT-Qpid-3-10K-P>-n LT-Qpid-3-10K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=10240 transacted=true -o $QPID_WORK/results</LT-Qpid-3-10K-P>
+ <LT-Qpid-4-10K-P>-n LT-Qpid-4-10K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=10240 -o $QPID_WORK/results</LT-Qpid-4-10K-P>
+
+ <LT-Qpid-3-50K-P>-n LT-Qpid-3-50K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=51200 transacted=true -o $QPID_WORK/results</LT-Qpid-3-50K-P>
+ <LT-Qpid-4-50K-P>-n LT-Qpid-4-50K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=51200 -o $QPID_WORK/results</LT-Qpid-4-50K-P>
+
+ <LT-Qpid-3-100K-P>-n LT-Qpid-3-100K-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=102400 transacted=true -o $QPID_WORK/results</LT-Qpid-3-100K-P>
+ <LT-Qpid-4-100K-P>-n LT-Qpid-4-100K-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=102400 -o $QPID_WORK/results</LT-Qpid-4-100K-P>
+
+ <LT-Qpid-3-1M-P>-n LT-Qpid-3-1M-P -d10M -s [1000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true commitBatchSize=100 messageSize=1048576 transacted=true -o $QPID_WORK/results</LT-Qpid-3-1M-P>
+ <LT-Qpid-4-1M-P>-n LT-Qpid-4-1M-P -d10M -s [100] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=1048576 -o $QPID_WORK/results</LT-Qpid-4-1M-P>
+
+ <!-- Failover Tests. -->
+ <!-- Transactional -->
+ <FT-Qpid-1-P>-n FT-Qpid-1-P -s [25000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" failBeforeSend=true -o $QPID_WORK/results</FT-Qpid-1-P>
+ <FT-Qpid-2-P>-n FT-Qpid-2-P -s [25000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" failAfterSend=true -o $QPID_WORK/results</FT-Qpid-2-P>
+ <FT-Qpid-3-P>-n FT-Qpid-3-P -s [25000] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 batchSize=10000 transacted=true broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" failAfterCommit=true -o $QPID_WORK/results</FT-Qpid-3-P>
+
+ <!-- Non Transactional -->
+ <FT-Qpid-4-P>-n FT-Qpid-4-P -s [250] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" transacted=false failBeforeSend=true -o $QPID_WORK/results</FT-Qpid-4-P>
+ <FT-Qpid-5-P>-n FT-Qpid-5-P -s [250] -t testAsyncPingOk org.apache.qpid.ping.PingAsyncTestPerf persistent=true messageSize=256 broker="tcp://10.0.0.1:5001;tcp://10.0.0.2:5002" transacted=false failAfterSend=true -o $QPID_WORK/results</FT-Qpid-5-P>
+
</commands>
</configuration>
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java b/qpid/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
index c0f236b833..eeb4021f34 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/client/message/TestMessageFactory.java
@@ -103,7 +103,7 @@ public class TestMessageFactory
{
StringBuffer buf = new StringBuffer(size);
int count = 0;
- while (count < size)
+ while (count <= (size - MESSAGE_DATA_BYTES.length()))
{
buf.append(MESSAGE_DATA_BYTES);
count += MESSAGE_DATA_BYTES.length();
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java b/qpid/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java
index 04381d66a0..14db74438f 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/config/AbstractConfig.java
@@ -49,7 +49,7 @@ public abstract class AbstractConfig
}
catch(NumberFormatException e)
{
- throw new RuntimeException(msg + ": " + i);
+ throw new RuntimeException(msg + ": " + i, e);
}
}
@@ -61,7 +61,7 @@ public abstract class AbstractConfig
}
catch(NumberFormatException e)
{
- throw new RuntimeException(msg + ": " + i);
+ throw new RuntimeException(msg + ": " + i, e);
}
}
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java b/qpid/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java
index 44285efd96..a0248a8f79 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/config/JBossConnectionFactoryInitialiser.java
@@ -22,6 +22,7 @@ package org.apache.qpid.config;
import org.apache.qpid.config.ConnectionFactoryInitialiser;
import org.apache.qpid.config.ConnectorConfig;
+import org.apache.qpid.client.JMSAMQException;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
@@ -63,11 +64,11 @@ public class JBossConnectionFactoryInitialiser implements ConnectionFactoryIniti
}
catch (NamingException e)
{
- throw new JMSException("Unable to lookup object: " + e);
+ throw new JMSAMQException("Unable to lookup object: " + e, e);
}
catch (Exception e)
{
- throw new JMSException("Error creating topic: " + e);
+ throw new JMSAMQException("Error creating topic: " + e, e);
}
}
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 82e43e542f..0e832ef100 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,3 +1,4 @@
+/* Copyright Rupert Smith, 2005 to 2006, all rights reserved. */
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -178,6 +179,7 @@ public class PingDurableClient extends PingPongProducer implements ExceptionList
// Run the test procedure.
int sent = pingProducer.send();
+ pingProducer.closeConnection();
pingProducer.waitForUser("Press return to begin receiving the pings.");
pingProducer.receive(sent);
@@ -302,6 +304,13 @@ public class PingDurableClient extends PingPongProducer implements ExceptionList
System.out.println("Messages sent: " + messagesSent + ", Messages Committed = " + messagesCommitted
+ ", Messages not Committed = " + messagesNotCommitted);
+
+
+ return messagesSent;
+ }
+
+ protected void closeConnection()
+ {
// Clean up the connection.
try
{
@@ -309,10 +318,11 @@ public class PingDurableClient extends PingPongProducer implements ExceptionList
}
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.
}
-
- return messagesSent;
}
protected void receive(int messagesSent) throws Exception
@@ -354,6 +364,32 @@ public class PingDurableClient extends PingPongProducer implements ExceptionList
}
}
+ // Ensure messages received are committed.
+ if (_transacted)
+ {
+ try
+ {
+ _consumerSession.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.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);
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
new file mode 100644
index 0000000000..7cf5e4516f
--- /dev/null
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/ping/PingSendOnlyClient.java
@@ -0,0 +1,57 @@
+/* Copyright Rupert Smith, 2005 to 2006, all rights reserved. */
+package org.apache.qpid.ping;
+
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+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[][] {}));
+ PingDurableClient 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);
+ }
+ }
+}
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 913685bca2..ecaf27167f 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
@@ -116,7 +116,7 @@ import uk.co.thebadgerset.junit.extensions.util.ParsedProperties;
* by the PPP that it is atteched to.
*
* @todo Use read/write lock in the onmessage, not for reading writing but to make use of a shared and exlcusive lock pair.
- * Obtian read lock on all messages, before decrementing the message count. At the end of the on message method add a
+ * 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.
@@ -725,6 +725,8 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
log.debug("public void createReplyConsumers(Collection<Destination> destinations = " + destinations
+ ", String selector = " + selector + "): called");
+ log.debug("Creating " + destinations.size() + " reply consumers.");
+
for (Destination destination : destinations)
{
// Create a consumer for the destination and set this pinger to listen to its messages.
@@ -732,6 +734,8 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
_consumerSession.createConsumer(destination, PREFETCH_DEFAULT, NO_LOCAL_DEFAULT, EXCLUSIVE_DEFAULT,
selector);
_consumer.setMessageListener(this);
+
+ log.debug("Set this to listen to replies sent to destination: " + destination);
}
}
@@ -743,13 +747,13 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
*/
public void onMessage(Message message)
{
- log.debug("public void onMessage(Message message): called");
+ // log.debug("public void onMessage(Message message): called");
try
{
// Extract the messages correlation id.
String correlationID = message.getJMSCorrelationID();
- log.debug("correlationID = " + correlationID);
+ // log.debug("correlationID = " + correlationID);
// Countdown on the traffic light if there is one for the matching correlation id.
PerCorrelationId perCorrelationId = perCorrelationIds.get(correlationID);
@@ -761,7 +765,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
// Restart the timeout timer on every message.
perCorrelationId.timeOutStart = System.nanoTime();
- log.debug("Reply was expected, decrementing the latch for the id, " + correlationID);
+ // log.debug("Reply was expected, decrementing the latch for the id, " + correlationID);
// 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
@@ -776,8 +780,8 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
trueCount = trafficLight.getCount();
remainingCount = trueCount - 1;
- log.debug("remainingCount = " + remainingCount);
- log.debug("trueCount = " + trueCount);
+ // 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.
@@ -806,23 +810,23 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
}
// Print out ping times for every message in verbose mode only.
- if (_verbose)
+ /*if (_verbose)
{
Long timestamp = message.getLongProperty(MESSAGE_TIMESTAMP_PROPNAME);
if (timestamp != null)
{
long diff = System.nanoTime() - timestamp;
- log.trace("Time for round trip (nanos): " + diff);
+ //log.trace("Time for round trip (nanos): " + diff);
}
- }
+ }*/
}
catch (JMSException e)
{
log.warn("There was a JMSException: " + e.getMessage(), e);
}
- log.debug("public void onMessage(Message message): ending");
+ // log.debug("public void onMessage(Message message): ending");
}
/**
@@ -955,16 +959,16 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
committed = false;
// Re-timestamp the message.
- message.setLongProperty(MESSAGE_TIMESTAMP_PROPNAME, System.nanoTime());
+ // 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)
+ /*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.
@@ -1003,7 +1007,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
_failBeforeSend = false;
}
- log.trace("Failing Before Send");
+ // log.trace("Failing Before Send");
waitForUser(KILL_BROKER_PROMPT);
}
@@ -1176,6 +1180,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
if (_connection != null)
{
_connection.close();
+ log.debug("Close connection.");
}
}
finally
@@ -1213,20 +1218,20 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
*/
protected boolean commitTx(Session session) throws JMSException
{
- log.debug("protected void commitTx(Session session): called");
+ // log.debug("protected void commitTx(Session session): called");
boolean committed = false;
- log.trace("Batch time reached");
+ // log.trace("Batch time reached");
if (_failAfterSend)
{
- log.trace("Batch size reached");
+ // log.trace("Batch size reached");
if (_failOnce)
{
_failAfterSend = false;
}
- log.trace("Failing After Send");
+ // log.trace("Failing After Send");
waitForUser(KILL_BROKER_PROMPT);
}
@@ -1241,14 +1246,14 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
_failBeforeCommit = false;
}
- log.trace("Failing Before Commit");
+ // log.trace("Failing Before Commit");
waitForUser(KILL_BROKER_PROMPT);
}
- long l = System.nanoTime();
+ // long l = System.nanoTime();
session.commit();
committed = true;
- log.debug("Time taken to commit :" + ((System.nanoTime() - l) / 1000000f) + " ms");
+ // log.debug("Time taken to commit :" + ((System.nanoTime() - l) / 1000000f) + " ms");
if (_failAfterCommit)
{
@@ -1257,15 +1262,15 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
_failAfterCommit = false;
}
- log.trace("Failing After Commit");
+ // log.trace("Failing After Commit");
waitForUser(KILL_BROKER_PROMPT);
}
- log.trace("Session Commited.");
+ // log.trace("Session Commited.");
}
catch (JMSException e)
{
- log.trace("JMSException on commit:" + e.getMessage(), e);
+ log.debug("JMSException on commit:" + e.getMessage(), e);
// Warn that the bounce back client is not available.
if (e.getLinkedException() instanceof AMQNoConsumersException)
@@ -1276,11 +1281,11 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
try
{
session.rollback();
- log.trace("Message rolled back.");
+ log.debug("Message rolled back.");
}
catch (JMSException jmse)
{
- log.trace("JMSE on rollback:" + jmse.getMessage(), jmse);
+ log.debug("JMSE on rollback:" + jmse.getMessage(), jmse);
// Both commit and rollback failed. Throw the rollback exception.
throw jmse;
@@ -1296,7 +1301,7 @@ public class PingPongProducer implements Runnable, MessageListener, ExceptionLis
*
* @param prompt The prompt to display on the console.
*/
- protected void waitForUser(String prompt)
+ public void waitForUser(String prompt)
{
System.out.println(prompt);
diff --git a/qpid/java/perftests/src/main/java/org/apache/qpid/topic/Config.java b/qpid/java/perftests/src/main/java/org/apache/qpid/topic/Config.java
index 342b28ca17..d5c0979399 100644
--- a/qpid/java/perftests/src/main/java/org/apache/qpid/topic/Config.java
+++ b/qpid/java/perftests/src/main/java/org/apache/qpid/topic/Config.java
@@ -221,7 +221,7 @@ public class Config extends AbstractConfig implements ConnectorConfig
}
catch(NumberFormatException e)
{
- throw new RuntimeException("Bad port number: " + value);
+ throw new RuntimeException("Bad port number: " + value, e);
}
}
else if("-payload".equalsIgnoreCase(key))
diff --git a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
index 3b8e670f8f..6c7f22c19a 100644
--- a/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
+++ b/qpid/java/perftests/src/test/java/org/apache/qpid/ping/PingAsyncTestPerf.java
@@ -133,12 +133,13 @@ public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerA
*/
public void testAsyncPingOk(int numPings) throws Exception
{
- _logger.debug("public void testAsyncPingOk(int numPings): called");
+ // _logger.debug("public void testAsyncPingOk(int numPings): called");
// Ensure that at least one ping was requeusted.
if (numPings == 0)
{
_logger.error("Number of pings requested was zero.");
+ fail("Number of pings requested was zero.");
}
// Get the per thread test setup to run the test through.
@@ -147,8 +148,8 @@ public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerA
// Advance the correlation id of messages to send, to make it unique for this run.
perThreadSetup._correlationId = Long.toString(corellationIdGenerator.incrementAndGet());
- String messageCorrelationId = perThreadSetup._correlationId;
- _logger.debug("messageCorrelationId = " + messageCorrelationId);
+ // String messageCorrelationId = perThreadSetup._correlationId;
+ // _logger.debug("messageCorrelationId = " + messageCorrelationId);
// Initialize the count and timing controller for the new correlation id.
PerCorrelationId perCorrelationId = new PerCorrelationId();
@@ -246,9 +247,9 @@ public class PingAsyncTestPerf extends PingTestPerf implements TimingControllerA
// Extract the correlation id from the message.
String correlationId = message.getJMSCorrelationID();
- _logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount
+ /*_logger.debug("public void onMessage(Message message, int remainingCount = " + remainingCount
+ "): called on batch boundary for message id: " + correlationId + " with thread id: "
- + Thread.currentThread().getId());
+ + Thread.currentThread().getId());*/
// Get the details for the correlation id and check that they are not null. They can become null
// if a test times out.
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
index 7c14de23a6..20de0d5df0 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java
@@ -44,9 +44,9 @@ public class AMQBrokerManagerMBeanTest extends TestCase
VirtualHost vHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test");
ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHost.VirtualHostMBean)vHost.getManagedObject());
- mbean.createNewExchange(exchange1,"direct",false, false);
- mbean.createNewExchange(exchange2,"topic",false, false);
- mbean.createNewExchange(exchange3,"headers",false, false);
+ mbean.createNewExchange(exchange1,"direct",false);
+ mbean.createNewExchange(exchange2,"topic",false);
+ mbean.createNewExchange(exchange3,"headers",false);
assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) != null);
assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) != null);
@@ -70,7 +70,7 @@ public class AMQBrokerManagerMBeanTest extends TestCase
assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null);
- mbean.createNewQueue(queueName, "test", false, true);
+ mbean.createNewQueue(queueName, "test", false);
assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null);
mbean.deleteQueue(queueName);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java
new file mode 100644
index 0000000000..52eb5414ff
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java
@@ -0,0 +1,208 @@
+package org.apache.qpid.server.failure;
+
+import junit.framework.TestCase;
+import org.apache.qpid.testutil.QpidClientConnection;
+import org.apache.qpid.client.failover.FailoverException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.log4j.Logger;
+
+import javax.jms.JMSException;
+import java.io.IOException;
+
+
+/** Test Case provided by client Non-functional Test NF101: heap exhaustion behaviour */
+public class HeapExhaustion extends TestCase
+{
+ private static final Logger _logger = Logger.getLogger(HeapExhaustion.class);
+
+ protected QpidClientConnection conn;
+ protected final String BROKER = "localhost";
+ protected final String vhost = "/test";
+ protected final String queue = "direct://amq.direct//queue";
+
+ protected String hundredK;
+ protected String megabyte;
+
+ protected String generatePayloadOfSize(Integer numBytes)
+ {
+ return new String(new byte[numBytes]);
+ }
+
+ protected void setUp() throws Exception
+ {
+ conn = new QpidClientConnection(BROKER);
+ conn.setVirtualHost(vhost);
+
+ conn.connect();
+ // clear queue
+ _logger.debug("setup: clearing test queue");
+ conn.consume(queue, 2000);
+
+ hundredK = generatePayloadOfSize(1024 * 100);
+ megabyte = generatePayloadOfSize(1024 * 1024);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ conn.disconnect();
+ }
+
+
+ /**
+ * PUT at maximum rate (although we commit after each PUT) until failure
+ *
+ * @throws Exception on error
+ */
+ public void testUntilFailure() throws Exception
+ {
+ int copies = 0;
+ int total = 0;
+ String payload = hundredK;
+ int size = payload.getBytes().length;
+ while (true)
+ {
+ conn.put(queue, payload, 1);
+ copies++;
+ total += size;
+ _logger.info("put copy " + copies + " OK for total bytes: " + total);
+ }
+ }
+
+ /**
+ * PUT at lower rate (5 per second) until failure
+ *
+ * @throws Exception on error
+ */
+ public void testUntilFailureWithDelays() throws Exception
+ {
+ int copies = 0;
+ int total = 0;
+ String payload = hundredK;
+ int size = payload.getBytes().length;
+ while (true)
+ {
+ conn.put(queue, payload, 1);
+ copies++;
+ total += size;
+ _logger.debug("put copy " + copies + " OK for total bytes: " + total);
+ Thread.sleep(200);
+ }
+ }
+
+ public static void noDelay()
+ {
+ HeapExhaustion he = new HeapExhaustion();
+
+ try
+ {
+ he.setUp();
+ }
+ catch (Exception e)
+ {
+ _logger.info("Unable to connect");
+ System.exit(0);
+ }
+
+ try
+ {
+ _logger.info("Running testUntilFailure");
+ try
+ {
+ he.testUntilFailure();
+ }
+ catch (FailoverException fe)
+ {
+ _logger.error("Caught failover:" + fe);
+ }
+ _logger.info("Finishing Connection ");
+
+ try
+ {
+ he.tearDown();
+ }
+ catch (JMSException jmse)
+ {
+ if (((AMQException) jmse.getLinkedException()).getErrorCode() == AMQConstant.REQUEST_TIMEOUT)
+ {
+ _logger.info("Successful test of testUntilFailure");
+ }
+ else
+ {
+ _logger.error("Test Failed due to:" + jmse);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.error("Test Failed due to:" + e);
+ }
+ }
+
+ public static void withDelay()
+ {
+ HeapExhaustion he = new HeapExhaustion();
+
+ try
+ {
+ he.setUp();
+ }
+ catch (Exception e)
+ {
+ _logger.info("Unable to connect");
+ System.exit(0);
+ }
+
+ try
+ {
+ _logger.info("Running testUntilFailure");
+ try
+ {
+ he.testUntilFailureWithDelays();
+ }
+ catch (FailoverException fe)
+ {
+ _logger.error("Caught failover:" + fe);
+ }
+ _logger.info("Finishing Connection ");
+
+ try
+ {
+ he.tearDown();
+ }
+ catch (JMSException jmse)
+ {
+ if (((AMQException) jmse.getLinkedException()).getErrorCode() == AMQConstant.REQUEST_TIMEOUT)
+ {
+ _logger.info("Successful test of testUntilFailure");
+ }
+ else
+ {
+ _logger.error("Test Failed due to:" + jmse);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.error("Test Failed due to:" + e);
+ }
+ }
+
+ public static void main(String args[])
+ {
+ noDelay();
+
+
+ try
+ {
+ System.out.println("Restart failed broker now to retest broker with delays in send.");
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ _logger.info("Continuing");
+ }
+
+ withDelay();
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
index 8795adbc55..0ad6502755 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MockProtocolSession.java
@@ -35,6 +35,7 @@ import org.apache.qpid.server.store.MessageStore;
import javax.security.sasl.SaslServer;
import java.util.HashMap;
import java.util.Map;
+import java.security.Principal;
/**
* A protocol session that can be used for testing purposes.
@@ -177,12 +178,12 @@ public class MockProtocolSession implements AMQProtocolSession
return ProtocolOutputConverterRegistry.getConverter(this);
}
- public void setAuthorizedID(String authorizedID)
+ public void setAuthorizedID(Principal authorizedID)
{
//To change body of implemented methods use File | Settings | File Templates.
}
- public String getAuthorizedID()
+ public Principal getAuthorizedID()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTest.java
new file mode 100644
index 0000000000..4ad10b68ff
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/PersistentTest.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQChannelClosedException;
+import org.apache.qpid.AMQConnectionClosedException;
+import org.apache.qpid.util.CommandLineParser;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.log4j.Logger;
+
+import javax.jms.Session;
+import javax.jms.JMSException;
+import javax.jms.Queue;
+import javax.jms.MessageProducer;
+import javax.jms.TextMessage;
+import java.io.IOException;
+import java.util.Properties;
+
+public class PersistentTest
+{
+ private static final Logger _logger = Logger.getLogger(PersistentTest.class);
+
+
+ private static final String QUEUE = "direct://amq.direct//PersistentTest-Queue2?durable='true',exclusive='true'";
+
+ protected AMQConnection _connection;
+
+ protected Session _session;
+
+ protected Queue _queue;
+ private Properties properties;
+
+ private String _brokerDetails;
+ private String _username;
+ private String _password;
+ private String _virtualpath;
+
+ public PersistentTest(Properties overrides)
+ {
+ properties = new Properties(defaults);
+ properties.putAll(overrides);
+
+ _brokerDetails = properties.getProperty(BROKER_PROPNAME);
+ _username = properties.getProperty(USERNAME_PROPNAME);
+ _password = properties.getProperty(PASSWORD_PROPNAME);
+ _virtualpath = properties.getProperty(VIRTUAL_HOST_PROPNAME);
+
+ createConnection();
+ }
+
+ protected void createConnection()
+ {
+ try
+ {
+ _connection = new AMQConnection(_brokerDetails, _username, _password, "PersistentTest", _virtualpath);
+
+ _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ _connection.start();
+ }
+ catch (Exception e)
+ {
+ _logger.error("Unable to create test class due to:" + e.getMessage(), e);
+ System.exit(0);
+ }
+ }
+
+ public void test() throws AMQException, URLSyntaxException
+ {
+
+ //Create the Durable Queue
+ try
+ {
+ _session.createConsumer(_session.createQueue(QUEUE)).close();
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Unable to create Queue due to:" + e.getMessage(), e);
+ System.exit(0);
+ }
+
+ try
+ {
+ if (testQueue())
+ {
+ // close connection
+ _connection.close();
+ // wait
+ System.out.println("Restart Broker Now");
+ try
+ {
+ System.in.read();
+ }
+ catch (IOException e)
+ {
+ //
+ }
+ finally
+ {
+ System.out.println("Continuing....");
+ }
+
+ //Test queue is still there.
+ AMQConnection connection = new AMQConnection(_brokerDetails, _username, _password, "DifferentClientID", _virtualpath);
+
+ AMQSession session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ try
+ {
+ session.createConsumer(session.createQueue(QUEUE));
+ _logger.error("Create consumer succeeded." +
+ " This shouldn't be allowed as this means the queue didn't exist when it should");
+
+ connection.close();
+
+ exit();
+ }
+ catch (JMSException e)
+ {
+ try
+ {
+ connection.close();
+ }
+ catch (JMSException cce)
+ {
+ if (cce.getLinkedException() instanceof AMQConnectionClosedException)
+ {
+ _logger.error("Channel Close Bug still present QPID-432, should see an 'Error closing session'");
+ }
+ else
+ {
+ exit(cce);
+ }
+ }
+
+ if (e.getLinkedException() instanceof AMQChannelClosedException)
+ {
+ _logger.info("AMQChannelClosedException received as expected");
+ }
+ else
+ {
+ exit(e);
+ }
+ }
+ }
+ }
+ catch (JMSException e)
+ {
+ _logger.error("Unable to test Queue due to:" + e.getMessage(), e);
+ System.exit(0);
+ }
+ }
+
+ private void exit(JMSException e)
+ {
+ _logger.error("JMSException received:" + e.getMessage());
+ e.printStackTrace();
+ exit();
+ }
+
+ private void exit()
+ {
+ try
+ {
+ _connection.close();
+ }
+ catch (JMSException e)
+ {
+ //
+ }
+ System.exit(0);
+ }
+
+ private boolean testQueue() throws JMSException
+ {
+ String TEST_TEXT = "init";
+
+ //Create a new session to send producer
+ Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+ Queue q = session.createQueue(QUEUE);
+ MessageProducer producer = session.createProducer(q);
+
+ producer.send(session.createTextMessage(TEST_TEXT));
+
+ //create a new consumer on the original session
+ TextMessage m = (TextMessage) _session.createConsumer(q).receive();
+
+
+ if ((m != null) && m.getText().equals(TEST_TEXT))
+ {
+ return true;
+ }
+ else
+ {
+ _logger.error("Incorrect values returned from Queue Test:" + m);
+ System.exit(0);
+ return 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 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 default configuration properties. */
+ public static Properties defaults = new Properties();
+
+ static
+ {
+ defaults.setProperty(BROKER_PROPNAME, BROKER_DEFAULT);
+ defaults.setProperty(USERNAME_PROPNAME, USERNAME_DEFAULT);
+ defaults.setProperty(PASSWORD_PROPNAME, PASSWORD_DEFAULT);
+ defaults.setProperty(VIRTUAL_HOST_PROPNAME, VIRTUAL_HOST_DEFAULT);
+ }
+
+ public static void main(String[] args)
+ {
+ PersistentTest test;
+
+ Properties options = CommandLineParser.processCommandLine(args, new CommandLineParser(new String[][]{}));
+
+
+ test = new PersistentTest(options);
+ try
+ {
+ test.test();
+ System.out.println("Test was successfull.");
+ }
+ catch (Exception e)
+ {
+ _logger.error("Unable to test due to:" + e.getMessage(), e);
+ }
+ }
+}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnection.java b/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnection.java
new file mode 100644
index 0000000000..80773c102d
--- /dev/null
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/testutil/QpidClientConnection.java
@@ -0,0 +1,268 @@
+package org.apache.qpid.testutil;
+
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.JMSAMQException;
+import org.apache.qpid.url.URLSyntaxException;
+import org.apache.log4j.Logger;
+
+import javax.jms.ExceptionListener;
+import javax.jms.Session;
+import javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Queue;
+import javax.jms.MessageProducer;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.TextMessage;
+
+public class QpidClientConnection implements ExceptionListener
+{
+
+ private static final Logger _logger = Logger.getLogger(QpidClientConnection.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 QpidClientConnection(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) throws JMSException
+ {
+ if (!connected)
+ {
+ connect();
+ }
+
+ _logger.info("putting to queue " + queueName);
+ Queue queue = session.createQueue(queueName);
+
+ final MessageProducer sender = session.createProducer(queue);
+
+ 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);
+ }
+}